使用SSE内在函数的大小为100 * 100的矩阵乘法

int MAX_DIM = 100; float a[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); float b[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); float d[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); /* * I fill these arrays with some values */ for(int i=0;i<MAX_DIM;i+=1){ for(int j=0;j<MAX_DIM;j+=4){ for(int k=0;k<MAX_DIM;k+=4){ __m128 result = _mm_load_ps(&d[i][j]); __m128 a_line = _mm_load_ps(&a[i][k]); __m128 b_line0 = _mm_load_ps(&b[k][j+0]); __m128 b_line1 = _mm_loadu_ps(&b[k][j+1]); __m128 b_line2 = _mm_loadu_ps(&b[k][j+2]); __m128 b_line3 = _mm_loadu_ps(&b[k][j+3]); result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0x00), b_line0)); result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0x55), b_line1)); result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0xaa), b_line2)); result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0xff), b_line3)); _mm_store_ps(&d[i][j],result); } } } 

我用上面的代码用SSE进行矩阵乘法。 代码作为流程运行我从行中取4个元素乘以b中的列中的4个元素并移动到b列中a和next 4个元素的行中的下4个元素

我得到一个错误Segmentation fault (core dumped)我真的不知道为什么

我在ubuntu 16.04.5上使用gcc 5.4.0

编辑:分段错误由_mm_loadu_ps解决。逻辑也有问题如果有人帮助我找到它,我会很高兴

_mm_loadu_ps也解决了_mm_loadu_ps错误。逻辑还有问题……

您正在b[k][j+0..7]上加载4个重叠窗口。 (这就是你需要loadu )。

也许你的意思是加载b[k][j+0]+4+8+12 ? 如果是这样,则应将b对齐64,因此所有四个加载都来自同一缓存行(性能)。 跨步访问并不是很好,但是使用你接触的每个缓存行的所有64个字节比在没有阻塞的标量代码中使行主要与列主要完全错误要好得多。

我从行中取4个元素乘以b 4个元素

我不确定您的文字说明是否描述了您的代码。

除非您已经转换了b ,否则无法使用SIMD加载从同一列加载多个值,因为它们在内存中不是连续的。

C多维数组是“行主要”:最后一个索引是移动到下一个更高内存地址时变化最快的索引。 您是否认为_mm_loadu_ps(&b[k][j+1])会给你b[k+0..3][j+1] ? 如果是这样,这是SSE矩阵 – 矩阵乘法的重复(该问题是使用32位整数,而不是32位浮点数,但布局问题相同。请参阅有关工作循环结构的信息。)


要调试它,将一个简单的值模式放入b[] 。 喜欢

 #include  alignas(64) float b[MAX_DIM][MAX_DIM] = { 0000, 0001, 0002, 0003, 0004, ..., 0100, 0101, 0102, ..., 0200, 0201, 0202, ..., }; // ie for (...) b[i][j] = 100 * i + j; 

然后,当您在调试器中单步调试代码时,可以看到向量中的值最终会出现。

对于a[][]值,也许使用90000.0 + 100 * i + j所以如果你正在查看寄存器(而不是C变量),你仍然可以知道哪些是a ,哪些是b


有关:

  • Ulrich Drepper的每个程序员应该知道的内存显示了一个优化的matmul,带有缓存阻塞和SSE内部函数,可实现双精度。 应该直接适应float

  • BLAS如何获得如此极端的性能? (您可能只想使用优化的matmul库;调整matmul以实现最佳缓存阻塞非常重要但非常重要)

  • 矩阵乘法与块
  • C vs Python / numpy中的数学表现不佳,与其他问题有一些联系
  • 如何优化矩阵乘法(matmul)代码,以便在单个处理器内核上快速运行