我实时收到Eigen::MatrixXf
和Eigen::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
是常数。 trans
和in_data
的大小分别为(4 x 4)
和(4 x n)
,其中n
大约为500,000。为了并行化for
循环,我尝试了OpenMP
,如上所示。但是,我认为for
循环的经过时间没有任何显着改善。
有什么建议吗?有什么替代方法可以执行相同的操作吗?
编辑:我的想法是定义4个(=COUNT
)个帖子,其中每个人都在处理乘法。通过这种方式,我想每次都不需要创建线程!
答案 0 :(得分:1)
您需要在编译和链接期间指定-fopenmp
。但是你很快就会达到极限,RAM访问正在停止进一步加速。你真的应该看看矢量内在函数。根据您的CPU,您可以将操作加速到寄存器的大小除以变量的大小(float = 4)。因此,如果你的处理器支持说AVX,你一次只能处理8个浮点数。如果您需要一些灵感,欢迎您从我的医学影像重建库中窃取代码:
https://github.com/kvahed/codeare/blob/master/src/matrix/SIMDTraits.hpp
代码完成整个shebang浮动/双重真实和复杂。
答案 1 :(得分:1)
使用以下自包含示例为我工作,也就是说,在启用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秒,在使用0.065秒时需要。