Могу ли я перебрать std :: tuple C ++ 11 с помощью openmp?

У меня есть следующий код для перебора std::tuple, Код отсюда Вот.

#include <tuple>
#include <utility>

template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_each(std::tuple<Tp...> &, FuncT) // Unused arguments are given no names.
{ }

template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(std::tuple<Tp...>& t, FuncT& f)
{
f(std::get<I>(t));
for_each<I + 1, FuncT, Tp...>(t, f);
}

Теперь я хотел бы выполнить это for_each цикл с openmp, так же, как я могу использовать openmp на for, Есть ли хитрость, чтобы сделать это возможным?

Примечание. Вы можете изменить приведенный выше код или использовать любую другую собственную версию. for_each,

3

Решение

Синтаксис шаблона C ++ 11 мне очень чужд, но рекурсивные проблемы, подобные этой, лучше всего делать параллельными, используя явные задачи OpenMP:

template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(std::tuple<Tp...>& t, FuncT& f)
{
#pragma omp task firstprivate(I) shared(t,f)
{
f(std::get<I>(t));
}
for_each<I + 1, FuncT, Tp...>(t, f);
}

...

// Proper usage
#pragma omp parallel
{
#pragma omp single
for_each(...);
}

Важная часть состоит в том, чтобы иметь вызов на высшем уровне for_each в single построить внутри parallel область, край. Таким образом, только один поток будет вызывать for_eachчто в свою очередь приведет к f(std::get<I>(t)); ставится в очередь для последующего выполнения в качестве явной задачи. Другие потоки, ожидая неявного барьера в конце single конструировать, начнет извлекать задачи из очереди задач и выполнять их параллельно, пока очередь не станет пустой. Классы совместного использования всех переменных, используемых задачей, даны явно для ясности.

Объекты, которые t а также f ссылка должна быть общей, а сами ссылки (в основном, указатели, которые реализуют ссылки) должны быть первыми. С другой стороны, стандарт OpenMP запрещает ссылочные типы быть частными, и разные поставщики компиляторов имеют тенденцию реализовывать стандарт по-разному. Компилятор Intel C ++ принимает следующий код и дает правильные результаты внутри задачи, но указанная переменная приватизирована (что неверно):

void f(int& p)
{
#pragma omp task
{
cout << "p = " << p << endl;
p = 3;
cout << "p' = " << p << endl;
}
}

void f1()
{
int i = 5;

#pragma omp parallel
{
#pragma omp single
f(i);
}
cout << "i = " << i << endl;
}

Компилятор PGI дает правильный результат и не приватизирует i, С другой стороны, GCC правильно определяет, что p должно быть firstprivate но затем сталкивается с запретом в стандарте и выдает ошибку времени компиляции.

Если кто-то изменяет задачу следующим образом:

#pragma omp task shared(p)
{
...
}

он работает правильно с GCC, но задача выводит неверное начальное значение p а затем вызывает ошибку сегментации как с компилятором Intel C ++, так и с компилятором PGI C ++.

Пойди разберись!

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]