2012-08-12 2 views
0

인텔 Cilk Plus 확장에는 cilk_for (또는 실제로 _Cilk_for 키워드)가 있습니다. 그것은 for 키워드와 같지만 좀 더 제한적이며 iteration은 병렬로 실행됩니다. 내부적으로 cilk_for를 사용하는 BOOST_FOREACH의 정신으로 편리한 매크로를 작성했습니다. 다음 구현에서 문제가 발생할 수 있습니까?foreach 매크로 구현에 문제가 있습니까

#pragma once 

#include <iterator> 
#include <boost/preprocessor/cat.hpp> 
#include <cilk/cilk.h> 

#define cilk_foreach(_decl_var_, _expr_range_) \ 
    CILK_FOREACH_I(_decl_var_, _expr_range_, __COUNTER__) 

#define CILK_FOREACH_I(_decl_var_, _expr_range_, _id_)    \ 
    CILK_FOREACH_II(_decl_var_,          \ 
        _expr_range_,         \ 
        BOOST_PP_CAT(_range_3s236dw221GyVcf46_, _id_), \ 
        BOOST_PP_CAT(_end_5Y60u42bIp7DZd88f2c_, _id_), \ 
        BOOST_PP_CAT(_itr_6V970q8n4Etv0i8bf50_, _id_), \ 
        BOOST_PP_CAT(_continue_4rtWH641r5cXqU_, _id_)) 

#define CILK_FOREACH_II(_decl_var_, _expr_range_, _range_, _end_, _itr_, _cont_) \ 
    auto&& _range_ = _expr_range_;            \ 
    auto _end_ = std::end(_range_);           \ 
                       \ 
    cilk_for (auto _itr_ = std::begin(_range_); _itr_ != _end_; ++_itr_)   \ 
     if (auto _cont_ = true)             \ 
      for (_decl_var_ = *_itr_; _cont_; _cont_ = false) 

당신은 너무처럼 사용합니다 :

std::vector<int> values (10); 

cilk_foreach (auto& value , values) 
{ 
    value += 123; 
} 

편집

template <typename T> 
struct Wrap 
{ 
    T& data; 

    explicit Wrap(T&& data) 
     : data (data) 
    {} 

    operator bool() const 
    { 
     return true; 
    } 
}; 

template <typename T> 
Wrap<T> wrap(T&& data) 
{ 
    return Wrap<T>(std::forward<T>(data)); 
} 

#define cilk_foreach(_decl_var_, _expr_range_) \ 
    CILK_FOREACH_I(_decl_var_, _expr_range_, __COUNTER__) 

#define CILK_FOREACH_I(_decl_var_, _expr_range_, _id_)    \ 
                    \ 
    CILK_FOREACH_II(_decl_var_,          \ 
        _expr_range_,         \ 
        BOOST_PP_CAT(_range_3s236dw221GyVcf46_, _id_), \ 
        BOOST_PP_CAT(_itr_6V970q8n4Etv0i8bf50_, _id_), \ 
        BOOST_PP_CAT(_continue_4rtWH641r5cXqU_, _id_)) 

#define CILK_FOREACH_II(_decl_var_, _expr_range_, _range_, _itr_, _cont_) \ 
                      \ 
    if (auto _range_ = wrap(_expr_range_))         \ 
     cilk_for (auto _itr_ = std::begin(_range_.data);     \ 
         _itr_ != std::end (_range_.data);     \ 
        ++_itr_)            \ 
      if (auto _cont_ = true)          \ 
       for (_decl_var_ = *_itr_; _cont_; _cont_ = false) 
+1

이 일을합니까? – Mat

+0

네, 테스트 해본 결과 거의 효과가있는 것 같습니다. BOOST_FOREACH 구현이 왜 그렇게 복잡한 지 혼란 스럽습니다. 위의 구현과 같은 단순한 구현도 가능합니다. 분명히 cilk_for의 모든 제한이 계속 적용되므로 범위가 임의 액세스 여야합니다. – zeroes00

+0

깔끔하지만, std :: for_each를 통해 얻은 이점은 무엇입니까? – dans3itz

답변

3

당신은 아마이 읽어야 C++ Boost: Any gotchas with BOOST_FOREACH?

한 명백한 문제가 당신의 마르코 아무튼입니다 가지고있는 어떤 것으로 확장하지 마라. 그것이있는 것처럼 보이는 어휘 유형.

#define foreach(ARRAY, ITEM) \ 
    for (size_t i = 0, b = 1; b && i != (ARRAY).size(); ++i, b = !b) \ 
     for (auto &ITEM = (ARRAY)[i]; b; b = 0) 

예, 그것은 몇 가지를 가지고 : 예를 들어,

if(condition) 
    cilk_foreach (auto& value , values) 
     // one-line stuff 
else 
    // other stuff 
+0

아, 이제 BOOST_FOREACH 구현이 나에게 의미가 있습니다. – zeroes00

2
Hurkyl에 의한 대답은 정확

가이 오류를 방지하기 위해 내가이 매크로를 사용

if(condition) 
    cilk_foreach (auto& value , values) { 
     //stuff 
    } 

또는 악화를 고려 단점은 있지만, 다른 답변처럼 중첩 된 경우에도 실제 for-loop 동작을 노출합니다. 중단하고 예상대로 작업을 계속하십시오.

그리고 당신은 다음과 같이 사용합니다 :

std::vector<int> values(10); 
foreach (values, val) 
    val += 123; 
+0

한 가지 단점은 일반 오래된 C 배열과 함께 사용할 수 없다는 것입니다. – bitmask

+0

'break'와 함께 작동하지 않는 것 같습니다. – Lol4t0

+0

죄송합니다, 지금은 내 게시물을 편집했습니다. – demorge

관련 문제