【发布时间】:2022-01-07 16:56:41
【问题描述】:
我想在 C 中有效地并行化以下总和:
#pragma omp parallel for num_threads(nth)
for(int i = 0; i < l; ++i) pout[pg[i]] += px[i];
其中px 是指向包含一些数据的大小为l 的双精度数组x 的指针,pg 是指向大小为l 的整数数组g 的指针,它将每个数据点分配到x 指向以随机顺序出现的 ng 组之一,pout 是指向大小为 ng 的双精度数组 out 的指针,该数组用零初始化并包含求和 x 的结果超过g定义的分组。
上面的代码可以工作,但性能不是最优的,所以我想知道我是否可以在 OpenMP 中做一些事情(例如reduction() 子句)来改进执行。数组的尺寸l 和ng,以及线程数nth 可供我使用并预先固定。我不能直接访问数组,只能将指针传递给执行并行求和的函数。
【问题讨论】:
-
如果您的编译器中的 OMP 支持,则迭代组或对整个
pout数组应用缩减 -
您展示的间接寻址方式与迭代代码所获得的 cache-unfriendly 差不多;然后你向它抛出多个线程,以便它们都可以竞争共享缓存。得知单线程执行性能如此出色时,我不会感到惊讶。
-
通过“上面的代码有效”,您的意思是没有 OpenMP pragma 的顺序实现,不是吗?否则,将是令人惊讶的。
l和ng在实践中有多大?您预计大约使用多少个线程?最佳结果算法将根据这些值发生很大变化。 -
感谢 cmets。代码是一些数据处理软件的内部组件,数组最多可以包含 1 亿个元素或更多。输入就像它们一样,重写整个事情以一次执行一组将是乏味的,而且不会更快。我是 C 编程 @HighPerformanceMark 的初学者,所以如果你能告诉我如何以更好的方式编写这个循环,我将不胜感激。就我的基准测试而言,使用指针并不比直接数组索引慢多少。并行执行使用 4 个线程可提供大约 2 倍的加速,因此不是最佳的。该软件在 PC 上运行。