我编写了下面的C函数,用平铺/分块和AVX向量相乘两个NxN矩阵,以加快计算速度。但是现在,当我尝试将AVX的本质和瓷砖结合起来时,我得到了一个分割错误。知道为什么会这样吗?
此外,是否有一个更好的内存访问模式的矩阵B?也许是先换位,甚至改变k和j循环?因为现在,我正在按列遍历它,这在空间局部性和缓存线方面可能不是很有效。
1 void mmult(double A[SIZE_M][SIZE_N], double B[SIZE_N][SIZE_K], double C[SIZE_M][SIZE_K])
2 {
3 int i, j, k, i0, j0, k0;
4 // double sum;
5 __m256d sum;
6 for(i0 = 0; i0 < SIZE_M; i0 += BLOCKSIZE) {
7 for(k0 = 0; k0 < SIZE_N; k0 += BLOCKSIZE) {
8 for(j0 = 0; j0 < SIZE_K; j0 += BLOCKSIZE) {
9 for (i = i0; i < MIN(i0+BLOCKSIZE, SIZE_M); i++) {
10 for (j = j0; j < MIN(j0+BLOCKSIZE, SIZE_K); j++) {
11 // sum = C[i][j];
12 sum = _mm256_load_pd(&C[i][j]);
13 for (k = k0; k < MIN(k0+BLOCKSIZE, SIZE_N); k++) {
14 // sum += A[i][k] * B[k][j];
15 sum = _mm256_add_pd(sum, _mm256_mul_pd(_mm256_load_pd(&A[i][k]), _mm256_broadcast_sd(&B[k][j])));
16 }
17 // C[i][j] = sum;
18 _mm256_store_pd(&C[i][j], sum);
19 }
20 }
21 }
22 }
23 }
24 }
发布于 2019-11-23 19:44:01
_mm256_load_pd
是一个对齐所需的加载,但您只需要按k++
执行,而不是在最内循环中加载4倍的32字节向量的k+=4
。所以它会发生故障,因为每4种负载中就有3种不对齐。
您不希望执行重叠加载,真正的错误是索引;如果您的输入指针是32字节对齐的,您应该能够继续使用_mm256_load_pd
而不是_mm256_loadu_pd
。因此,使用_mm256_load_pd
成功地捕获了您的错误,而不是工作,但是给出了错误的数字结果。
将四个row*column
C[i][j+0..3]
点产品矢量化(以生成C[i][j+0..3]
向量)的策略是,应该从4个不同的列加载4个连续的双打(通过B[k][j]
的向量加载来加载B[k][j+0..3]
),并从A[i][k]
中播放1个double。记住,你想要4个点的产品并行。
另一种策略可能会涉及到最后的水平和,直到标量C[i][j] += horizontal_add(__m256d)
,但我认为这需要先转置一个输入,这样行向量和列向量都在一个点积的连续内存中。但是,在每个内环的末尾,你需要进行水平和的洗牌。
您可能还希望至少使用2个sum
变量,这样就可以同时读取整个缓存行,并将FMA延迟隐藏在内部循环中,并有望成为吞吐量的瓶颈。或更好地并行处理4或8个向量。使您生成C[i][j+0..15]
作为sum0
、sum1
、sum2
、sum3
。(或者使用__m256d
数组;编译器通常会完全展开8的循环,并将数组优化为寄存器。)
我认为您只需要5个嵌套循环,就可以阻塞行和列。虽然很明显,6个嵌套循环是一个有效的选项:参见loop tiling/blocking for large dense matrix multiplication,它在问题中有一个5嵌套循环,但在一个答案中有一个6嵌套循环。(只是标量,而不是矢量化)。
在这里,除了行*列点产品策略之外,可能还有其他错误,我不确定。
如果您使用的是AVX,您可能也想使用FMA,除非您需要运行在Sandbybridge/Ivybridge和AMD推土机上。(河床和后来有FMA3)。
其他matmul策略包括在内循环中添加目标,这样您就可以在内环中加载C
和A
,并从B
加载。(或者B和A交换了,我忘记了。) What Every Programmer Should Know About Memory?有一个矢量化缓存阻塞的例子,在附录中是这样工作的,用于SSE2 __m128d
向量。https://www.akkadia.org/drepper/cpumemory.pdf
https://stackoverflow.com/questions/59009628
复制相似问题