parallel-processing - 在矩阵向量乘法中使用 OpenMP“for simd”?
问题描述
我目前正在尝试通过与 组合使我的矩阵向量乘法函数与 BLAS 进行比较#pragma omp for
,#pragma omp simd
但与仅使用 for 构造相比,它没有得到任何加速改进。如何使用 OpenMP 的 SIMD 构造正确矢量化内部循环?
vector dot(const matrix& A, const vector& x)
{
assert(A.shape(1) == x.size());
vector y = xt::zeros<double>({A.shape(0)});
int i, j;
#pragma omp parallel shared(A, x, y) private(i, j)
{
#pragma omp for // schedule(static)
for (i = 0; i < y.size(); i++) { // row major
#pragma omp simd
for (j = 0; j < x.size(); j++) {
y(i) += A(i, j) * x(j);
}
}
}
return y;
}
解决方案
您的指令不正确,因为会引入竞争条件(on y(i)
)。在这种情况下,您应该使用减少。这是一个例子:
vector dot(const matrix& A, const vector& x)
{
assert(A.shape(1) == x.size());
vector y = xt::zeros<double>({A.shape(0)});
int i, j;
#pragma omp parallel shared(A, x, y) private(i, j)
{
#pragma omp for // schedule(static)
for (i = 0; i < y.size(); i++) { // row major
decltype(y(0)) sum = 0;
#pragma omp simd reduction(+:sum)
for (j = 0; j < x.size(); j++) {
sum += A(i, j) * x(j);
}
y(i) += sum;
}
}
return y;
}
请注意,可能不需要更快,因为某些编译器能够自动矢量化代码(例如 ICC)。GCC 和 Clang 经常无法自动执行(高级)SIMD 缩减,这样的指令可以帮助他们一点。您可以检查汇编代码以检查代码是如何矢量化的或启用矢量化报告(有关 GCC,请参见此处)。
推荐阅读
- bash - 运行 bash 脚本时需要整数表达式
- javascript - 如何在 Node-RED 中拆分 JSON 字符串后提取值
- react-native - undefined 不是一个对象(评估'_firebase.firebase.firestore
- amazon-web-services - SQS 上的审核消息
- oracle - 单一模式中的 TDE 多个主加密密钥
- angular - angular7 ag-grid this.http 是未定义的错误
- jekyll - Jekyll CMS 将语言数据文件插入另一个数据文件
- scroll - 如何启用 QBasic 输出窗口的滚动条?
- javascript - 选择下拉列表中的复选框后如何清除 v-autocomplete(多个)搜索输入?
- angular - 如何使用formbuilder获取离子选择多个数据并将其发布为数组