我正在尝试编写Ising模型的蒙特卡罗模拟,我想知道是否可以使用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)
是一种访问std::vector
个short
的单位SIMD
的方法。我看到可能存在一些问题:访问有很多三元逻辑(对于周期性边界条件),并且没有一个向量元素是相邻的。是为了对这个块进行No Column Sum
0 Company 28
1 Booth 28
2 Full-Time 25
3 Full-Time Visa Sponsor 5
4 Part-Time 1
5 Internship 18
6 Freshman 7
7 Sophomore 9
8 Junior 17
9 Senior 24
10 Post-Bacs 17
11 MS 17
12 PhD 6
13 Alumni 15
优化,还是应该继续挖掘?重新实现邻接矩阵和/或使用不同的容器(例如,阵列或不同类型的矢量)是一种选择。
答案 0 :(得分:3)
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]);
请注意,迷你阵列预先计算了域中相邻单元的偏移量。一个好的编译器可能会展开前面的循环。
完成所有这些后,适当选择优化标记可能会导致自动矢量化。
实际上,代码中的分支和mod可能会阻止自动矢量化。您可以通过启用适当的标志来检查。对于英特尔编译器集合(icc),您需要:
-qopt-report=5 -qopt-report-phase:vec
对于GCC,你想要(如果我没记错的话):
-fopt-info-vec -fopt-info-missed