【发布时间】:2018-09-25 01:08:08
【问题描述】:
我正在尝试编写 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) 是访问shorts 的平面std::vector 的方法。我看到可能存在一些问题:访问有很多三元逻辑正在进行(对于周期性边界条件),并且没有一个向量元素是相邻的。是对这个块进行SIMD 优化,还是我应该继续挖掘?重新实现邻接矩阵和/或使用不同的容器(例如数组或不同类型的向量)是一种选择。
【问题讨论】:
-
您可以考虑并行运行 4 次模拟,或者使用像
struct { align(16) int elem0, elem1, elem2, elem3; } array[something];这样的交错数组来运行,但这会使用 4 倍的 RAM,并且只有当您可以将 4 次较短模拟的结果合并到 1 个大蒙特中时才会有所帮助-carlo 模拟。 -
您是否同时为所有单元格计算此值? SIMD 可以帮助您同时计算 4 或 8 个单元。
-
@PeterCordes,不,我需要独立的模拟。 @chtz,显然它只能帮助预加载在底层向量中相邻的两个单元格(事实证明编译器已经使用
-O3执行此操作)。我更多的是在想:如何重新排列数据以使 SIMD 在所有 4 上成为可能。 -
chtz 询问您是否使用此函数遍历所有行和列。如果是这样,则在将其内联到该循环后寻找优化(即并行计算 4 或 8 个结果,而不是尝试通过大量昂贵的改组来加速一个结果的计算。)这将使从 @ 加载 4 个相邻值987654328@ 和
row+1很有用,例如:您可以使用“垂直”添加来获取向量中的data[row-1][col+0..3] + data[row+1][col+0..3]。你需要一些洗牌来处理中间块的水平加法,但是结果之间有一些部分和的重用