OpenMP中使用字符串类型进行归约

时间:2018-12-16 20:17:07

标签: c++ optimization openmp

我正在使用OpenMP使for循环像这样

std::stringType = "somevalue";
#pragma omp parallel for reduction(+ : stringType)
//a for loop here which every loop appends a string to stringType

我能想到的唯一方法是先以某种方式转换为int表示形式,然后在最后转换回原来的形式,但这有明显的开销。有没有更好的方法来执行这种操作方式?

1 个答案:

答案 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调用)。