在 OpenMP 中使用并行块时没有看到任何显着改进C++



我实时收到一系列Eigen::MatrixXfEigen::Matrix4f。这两个数组具有相同数量的元素。我所要做的就是将两个数组的元素相乘,并将结果存储在同一索引的另一个数组中。

请参阅下面的代码片段-

#define COUNT 4
while (all_ok())
{
Eigen::Matrix4f    trans[COUNT];
Eigen::MatrixXf  in_data[COUNT];
Eigen::MatrixXf out_data[COUNT];
// at each iteration, new data is filled
// in 'trans' and 'in_data' variables
#pragma omp parallel num_threads(COUNT)
{
#pragma omp for
for (int i = 0; i < COUNT; i++)
out_data[i] = trans[i] * in_clouds[i];
}
}

请注意,COUNT是一个常数。transin_data的大小分别为(4 x 4)(4 x n),其中n约为500,000。为了并行化for循环,我尝试了OpenMP如上所示。但是,我没有看到循环的经过时间有任何显着for改善。

有什么建议吗?请问是否有其他方法可以执行相同的操作?

编辑:我的想法是定义4(=COUNT(线程,其中每个线程都负责乘法。这样,我们不需要每次都创建线程,我猜!

使用以下自包含示例为我工作,也就是说,我在启用 openmp 时获得了 x4 加速:

#include <iostream>
#include <bench/BenchTimer.h>
using namespace Eigen;
const int COUNT = 4;
EIGEN_DONT_INLINE
void foo(const Matrix4f *trans, const MatrixXf *in_data, MatrixXf *out_data)
{
#pragma omp parallel for num_threads(COUNT)
for (int i = 0; i < COUNT; i++)
out_data[i] = trans[i] * in_data[i];
}
int main()
{
Eigen::Matrix4f    trans[COUNT];
Eigen::MatrixXf  in_data[COUNT];
Eigen::MatrixXf out_data[COUNT];
int n = 500000;
for (int i = 0; i < COUNT; i++)
{
trans[i].setRandom();
in_data[i].setRandom(4,n);
out_data[i].setRandom(4,n);
}
int tries = 3;
int rep = 1;
BenchTimer t;
BENCH(t, tries, rep, foo(trans, in_data, out_data));
std::cout << " " << t.best(Eigen::REAL_TIMER) << " (" << double(n)*4.*4.*4.*2.e-9/t.best() << " GFlops)n";
return 0;
}

因此,1(确保测量的是挂钟时间而不是CPU时间,2(确保产品是瓶颈而不是填充in_data

最后,为了获得最大的性能,不要忘记启用AVX/FMA(例如,使用-march=native(,当然,请确保使用编译器的优化进行基准测试。

作为记录,在我的计算机上,上面的例子在没有 openmp 的情况下需要 0.25 秒,而没有 openmp 需要 0.065 秒。

您需要在编译和链接期间指定-fopenmp。但是您很快就会达到极限,RAM 访问正在停止进一步加速。你真的应该看看向量内联函数。根据 CPU 的不同,您可以将操作加速到寄存器的大小除以变量的大小(float = 4(。因此,如果您的处理器支持 AVX,您将一次处理 8 个浮点数。如果您需要一些灵感,欢迎您从我的医学图像重建库中窃取代码: https://github.com/kvahed/codeare/blob/master/src/matrix/SIMDTraits.hpp 该代码为浮点/双实数和复杂执行整个 shebang。

最新更新