2015-04-23 1 views
1

J'ai une fonction variadique modèle comme celui-ci qui ont besoin de paralléliser avec fonction TBB parallel_forComment paralléliser la fonction variadique avec TBB parallel_for?

template<typename T1, typename T2, typename... T3> 
void func(T1 t1, T2 t2, std::size_t n, T3... t3) 

J'ai d'abord essayé d'utiliser une fonction lambda, il est en mesure de saisir les arguments variadique. Il compilé avec clang en utilisant la fonctionnalité C++ 11.

template<typename T1, typename T2, typename... T3> 
void parallel_func(T1 t1, T2 t2, std::size_t n, T3 t3...){ 
    range r(n); 
    apply_func = [=](range r){ //clang 6.1 can catch t3... here, gcc 4.8.3 could not 
     std::size_t offset = r.begin(); 
     std::size_t n = r.end() -r.begin(); 
     func(t1, t2, n, (t3+offset)...); 
    }; 
    tbb::parallel_for(r, apply_func); 
} 

Toutefois, le cluster que j'utilise ne possède pas de compilateur pour prendre en charge cette fonctionnalité. Je dois abandonner la fonction de lambda et écrire une classe et la passer à la fonction parallel_for. Je essayé:

template<typename T1, typename T2, typename... T3> 
class ApplyFunc{ 
    ApplyFunc(T1 t1, T2 t2, T3... t3){ 
     t1_ = t1; 
     t2_ = t2; 
     t3_ = t3...; 

    } 
     void operator(range r){ 
     std::size_t offset = r.begin(); 
     std::size_t n = r.end() -r.begin(); 
     func(T1, T2, n, (T3+offset)...); 
     } 
     private: 
     T1 t1_; 
     T2 t2_; 
     T3... t3_; 
} 

apparemment variable variadique n'est pas pris en charge. J'ai essayé std :: tuple t3_; Cependant, je ne suis pas en mesure de convertir std::tuple<T3...> en arguments variadiques.

+0

Vous compilez le code sur cluster où vous ne disposez pas du support C++ 11? – Jagannath

+1

@Jagannath c'est gcc 4.8. Ce qui ne supporte pas lambda avec des arguments variadiques. – RealityPC

+0

Désolé ne pouvait pas comprendre exactement. 'parallel_for' prend l'index de début et de fin pour parcourir. Alors, comment passez-vous la classe? Pourriez-vous utiliser 'parallel_for_each' et prendre tous ces arguments dans un' std :: tuple' et avoir 'begin' et' end' dans votre classe. Ça marchera ? – Jagannath

Répondre

1

Vous pouvez utiliser std::tuple<Ts...> pour conserver des valeurs variées et l'étendre pour l'appel de fonction avec the indices trick. La bibliothèque standard C++ 14 fournit std::index_sequence à cette fin.

#include <tuple> 

// forward compatibility for C++14 Standard Library 
namespace cxx14 { 
template<std::size_t...> struct index_sequence{}; 

template<std::size_t N, std::size_t... Is> 
struct make_index_sequence : make_index_sequence<N-1, N-1, Is...>{}; 

template<std::size_t... Is> 
struct make_index_sequence<0, Is...> : index_sequence<Is...>{}; 
} 

template<typename T1, typename T2, typename... Ts> 
class ApplyFunc{ 
public: 
    ApplyFunc(T1 t1, T2 t2, Ts... ts) 
    : t1_(t1), t2_(t2), pack_(ts...) {} 

    template<std::size_t... Is> 
    void call(range r, cxx14::index_sequence<Is...>){ 
    std::size_t offset = r.begin(); 
    std::size_t n = r.end() - r.begin(); 
    func(t1_, t2_, n, (std::get<Is>(pack_)+offset)...); 
    } 

    void operator()(range r){ 
    call(r, cxx14::make_index_sequence<sizeof...(Ts)>()); 
    } 
private: 
    T1 t1_; 
    T2 t2_; 
    std::tuple<Ts...> pack_; 
}; 
+0

est-ce que gcc 4.8.3 supporte cela? – RealityPC

+0

gcc 4.8.2 et 4.8.3 seront. [LiveDemo] (http://melpon.org/wandbox/permlink/vSGnMVT6UqpuQaRO) – yohjp

+0

génial! Je vais essayer. Je vous remercie! – RealityPC