我正在使用OpenMP使for循环像这样
std::stringType = "somevalue";
#pragma omp parallel for reduction(+ : stringType)
//a for loop here which every loop appends a string to stringType
我能想到的唯一方法是先以某种方式转换为int表示形式,然后在最后转换回原来的形式,但这有明显的开销。有没有更好的方法来执行这种操作方式?
答案 0 :(得分:2)
如评论中所述,归约假设操作是关联的和可交换的。这些值可以按任何顺序计算,并可以通过任何种类的部分结果“累加”,最终结果将是相同的。
除非循环时间表明确要求,否则无法保证OpenMP for循环会将连续的迭代分配给每个线程。也不保证通过增加线程数来分配连续的块(即线程#0可能经历1000-1999迭代,而线程#1可能经历0-999)。如果您需要这种行为,则应该定义自己的时间表。
类似的东西:
int N=1000;
std::string globalString("initial value");
#pragma omp parallel shared(N,stringType)
{
std::string localString; //Empty string
// Set schedule
int iterTo, iterFrom;
iterFrom = omp_get_thread_num() * (N / omp_get_num_threads());
if (omp_get_num_threads() == omp_get_thread_num()+1)
iterTo = N;
else
iterTo = (1+omp_get_thread_num()) * (N / omp_get_num_threads());
// Loop - concatenate a number of neighboring values in the right order
// No #pragma omp for: each thread goes through the loop, but loop
// boundaries change according to the thread ID
for (int ii=iterTo; ii<iterTo ; ii++){
localString += get_some_string(ii);
}
// Dirty trick to concatenate strings from all threads in the good order
for (int ii=0;ii<omp_get_num_threads();ii++){
#pragma omp barrier
if (ii==omp_get_thread_num())
globalString += localString;
}
}
更好的方法是拥有std::string
的共享数组,每个线程都使用一个作为本地累加器。最后,一个线程可以运行串联部分(并避免肮脏的把戏及其所有繁重的barrier
调用)。