针对跨模式访问的 SIMD 优化

SIMD optimisation for cross-pattern access

本文关键字:SIMD 优化 访问 模式      更新时间:2023-10-16

我正在尝试编写伊辛模型的蒙特卡罗模拟,我想知道是否可以使用 SIMD 优化来访问交叉模式中的数据。

我基本上想知道是否有任何方法可以加速此功能。

//up/down/left/right stencil accumulation
float lattice::compute_point_energy(int row, int col) {
int accumulator=0;
accumulator+= get(row? row-1: size_-1, col);
accumulator+= get((row+1)%size_, col);
accumulator+= get(row, col? col-1: size_-1);
accumulator+= get(row, (col+1)%size_) ;
return -get(row, col) * (accumulator * J_ + H_);
}

get(i, j)是一种访问shorts 的平面std::vector的方法。我看到可能存在一些问题:访问有很多三元逻辑(对于周期性边界条件),并且没有一个向量元素是相邻的。是为了对这个区块进行SIMD优化,还是我应该继续挖掘?重新实现邻接矩阵和/或使用不同的容器(例如数组或不同类型的向量)是一种选择。

SIMD 是您要尝试使用此函数的最后一件事。

我认为您正在尝试使用上/下/左/右 4 模板进行计算。如果是这样,您的代码应该有一个注释来说明这一点。

在这个函数中,你会失去很多速度,因为你的三元运算符可能会分支,而且模量相对较慢。

您最好用一圈设置为适合处理边缘效果的值的单元格包围您正在操作的二维空间。这使您可以消除对边缘效果的检查。

为了访问您的模板,我发现使用如下所示的内容通常有效:

const int width  = 10;
const int height = 10;
const int offset[4] = {-1,1,-width,width};
double accumulator=0;
for(int i=0;i<4;i++)
accumulator += get(current_loc+offset[i]);

请注意,迷你数组已预先计算了域中相邻单元格的偏移量。一个好的编译器可能会展开上述循环。

完成所有这些操作后,适当选择优化标志可能会导致自动矢量化。

实际上,代码中的分支和模组可能会阻止自动矢量化。您可以通过启用适当的标志来检查这一点。对于英特尔编译器软件集 (ICC),您需要:

-qopt-report=5 -qopt-report-phase:vec

对于 GCC,您需要(如果我没记错的话):

-fopt-info-vec -fopt-info-missed