在 std::vector 上的 Openmp 和减少?

我想让这段代码并行:

std::vectorres(n,0);std::vector值(米);std::vector指数(米);//用 [0,n) 范围内的值填充索引//填充值和索引for(size_t i=0; i

在这篇文章中,建议使用:>

#pragma omp parallel for reduction(+:myArray[:6])

在这个问题中,评论部分提出了相同的方法.>

我有两个问题:

  1. 我在编译时不知道 m ,从这两个示例看来,这是必需的.是这样吗?或者,如果我可以在这种情况下使用它,我必须用以下命令替换 ? 用以下命令 #pragma omp parallel for reduction(+:res[:?]) ?m 还是 n?
  2. for 的索引是否与 indexesvals 相关,而不与 res 相关, 特别是考虑到 reduction 是在后一个上做的?

但是,如果是这样,我该如何解决这个问题?

解决方案

对特定类型的 C++ 向量执行用户声明的归约是相当直接的:

#include <算法>#include <向量>#pragma omp 声明减少(vec_float_plus : std::vector<float> : std::transform(omp_out.begin(), omp_out.end(), omp_in.begin(), omp_out.begin(), std::plus())) 初始值设定项(omp_priv = decltype(omp_orig)(omp_orig.size()))std::vectorres(n,0);#pragma omp 并行减少(vec_float_plus : res)for(size_t i=0; i

1a) 在编译时不知道 m 不是必需的.

1b) 您不能在 std::vector 上使用数组节缩减,因为它们不是数组(并且 std::vector::data 不是一个标识符).如果可能,您必须使用 n,因为这是数组部分中的元素数.

2) 只要??您只读取indexesvals,就没有问题.

原来的initializer caluse 更简单:initializer(omp_priv = omp_orig).但是,如果原始副本没有全零,结果将是错误的.因此,我建议使用更复杂的初始化器,它总是创建零元素向量.

I want to make this code parallel:

std::vector<float> res(n,0);
std::vector<float> vals(m);
std::vector<float> indexes(m);
// fill indexes with values in range [0,n)
// fill vals and indexes
for(size_t i=0; i<m; i++){
  res[indexes[i]] += //something using vas[i];
}

In this article it's suggested to use:

#pragma omp parallel for reduction(+:myArray[:6])

In this question the same approach is proposed in the comments section.

I have two questions:

  1. I don't know m at compile time, and from these two examples it seems that's required. Is it so? Or if I can use it for this case, what do I have to replace ? with in the following command #pragma omp parallel for reduction(+:res[:?]) ? m or n?
  2. Is it relevant that the indexes of the for are relative to indexes and vals and not to res, especially considering that reduction is done on the latter one?

However, If so, how can I solve this problem?

解决方案

It is fairly straight forward to do a user declared reduction for C++ vectors of a specific type:

#include <algorithm>
#include <vector>

#pragma omp declare reduction(vec_float_plus : std::vector<float> : 
                              std::transform(omp_out.begin(), omp_out.end(), omp_in.begin(), omp_out.begin(), std::plus<float>())) 
                    initializer(omp_priv = decltype(omp_orig)(omp_orig.size()))

std::vector<float> res(n,0);
#pragma omp parallel for reduction(vec_float_plus : res)
for(size_t i=0; i<m; i++){
    res[...] += ...;
}

1a) Not knowing m at compile time is not a requirement.

1b) You cannot use the array section reduction on std::vectors, because they are not arrays (and std::vector::data is not an identifier). If it were possible, you'd have to use n, as this is the number of elements in the array section.

2) As long as you are only reading indexes and vals, there is no issue.

Edit: The original initializer caluse was simpler: initializer(omp_priv = omp_orig). However, if the original copy is then not full of zeroes, the result will be wrong. Therefore, I suggest the more complicated initializer which always creates zero-element vectors.

相关文章