【问题标题】:SIMD optimisation for cross-pattern access跨模式访问的 SIMD 优化
【发布时间】: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]。你需要一些洗牌来处理中间块的水平加法,但是结果之间有一些部分和的重用

标签: c++ simd


【解决方案1】:

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]);

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

Once you've done all this, appropriate choice of optimization flags may lead to automatic vectorization.

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

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

对于 GCC,你会想要(如果我没记错的话):

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

【讨论】:

  • 这是个好主意。 gcc 命令不起作用,否则回答了我需要的所有内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-07
  • 2019-05-29
  • 1970-01-01
  • 2011-01-08
  • 2022-12-04
  • 2020-12-05
相关资源
最近更新 更多