C++ 矩阵乘法自动向量化

问题描述 投票:0回答:4

我启用了自动矢量化。当我编译代码时,我收到以下警告:

info C5002: loop not vectorized due to reason '1203'

MSDN 指定

循环体包括对数组的非连续访问。

我查看了这些链接,12,寻求帮助,但没有运气。

这是我的源代码:

for (int row = 0; row < size; ++row) {
    for (int col = 0; col < size; ++col) {
        float tmp = 0;
        for (int i = 0; i < size; ++i) { // This loop generates the warning above
            tmp += matrixA[row][i] * matrixB[i][col];
        }
        matrixResult[row][col] = tmp;
    }
}

欢迎任何帮助。

c++ matrix-multiplication visual-studio-2017 simd auto-vectorization
4个回答
2
投票

2D 数组存储为单个连续的内存块,因此 3x2 元素的 2D 数组实际上是首尾相连的 6 个元素。

[] 索引运算符简单地计算要访问的元素。

所以这里发生的是从元素 1 到元素 6 顺序访问矩阵 A(即 A1、A2、A3、B1、B2、B3)。

matrixB 然而,被“随机”访问,A1、B1、A2、B2 等映射到实际存储作为访问元素 1 然后 4 然后 2 然后 5.

您不能更改访问 matrixB 元素的顺序,但可以转置它,以便元素按正确的顺序顺序访问。显然,如果你只做一次乘法,重新计算 matrixBs 的顺序可能不值得,但如果你重复执行这个计算,那么这些努力将是非常值得的。


1
投票

如果矩阵

A
B
具有相同的存储顺序(例如行专业),那么您无论如何都不能对其进行向量化。所以这使得警告合理。

这里只是一个建议:如果你想要真正的高性能计算,那么你应该放弃二维数组。缓存的增益远大于矢量化加速。


1
投票

实现连续访问的一种方法:您可以交换内部两个循环。而不是

for row, for col, for i
你有
for row, for i, for col
。请参阅下面的结果代码。现在
matrixResult
matrixB
的访问都沿着
col
,所以它是连续的。

for (int row = 0; row < size; ++row) {
    for (int i = 0; i < size; ++i) {
        int a_row_i = matrixA[row][i];
        for (int col = 0; col < size; ++col) {
            matrixResult[row][col] += a_row_i * matrixB[i][col];
        }
    }
}

1
投票

这对我有用:

#define N 1000

void example(int A[N][N], int B[N][N], int C[N][N]) {
    for (int i=0; i<N; i++) {
        for (int j=0; j<N; j++) {
            int res = 0;
            #pragma clang loop vectorize(enable) vectorize_width(8)
            for (int k=0; k<N; k++) {
                res += A[i][k] * B[j][k];
            }
            C[i][j] = res;
        }
    }
}

https://godbolt.org/z/K4foqd37T

更新(感谢@Peter Cordes):如果一个输入矩阵已经被转置,那将有效,

© www.soinside.com 2019 - 2024. All rights reserved.