C ++:改进现有的C程序性能

时间:2014-05-05 16:20:17

标签: c++ performance visual-studio caching matrix

我有以下代码片段,可以将2×1024字段的矩阵相乘得到结果时间:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h>

#define NUM 1024
float a[NUM][NUM],b[NUM][NUM],c[NUM][NUM]; 
void initialize_matrix(float m[][NUM]); 
void load_matrix(float m[][NUM]); 

int main() {

    int i,j,k; 

    clock_t t_inicial,t_final; 
    load_matrix(a); 
    load_matrix(b); 
    initialize_matrix(c); 

    printf("Starting matrix multiplication 1024x1024...\n\n");

    t_inicial=clock();
    for(i=0;i<NUM;i++) 
    for(j=0;j<NUM;j++) 
    for(k=0;k<NUM;k++) 
    c[i][j] =c[i][j] + a[i][k] * b[k][j]; 
    t_final=clock();

    printf("Matrix multiplication finished in: %3.6f seconds",((float) t_final- (float)t_inicial)/CLOCKS_PER_SEC);

} 

void initialize_matrix(float m[][NUM]) {

    int i,j;
    for(i=0;i<NUM;i++) 
    for(j=0;j<NUM;j++) 
    m[i][j]=0.0; 
    return;

} 
void load_matrix(float m[][NUM]) {

    int i,j;
    #pragma omp parallel for
    for(i=0;i<NUM;i++) 
    for(j=0;j<NUM;j++) 
    m[i][j]=(float) 10*rand()/(float) rand(); 
    return;

}

此代码需要24秒才能解决,我已经被告知缓存内存有问题。如何改进此代码以缩短时间?它花了这么长时间并不是很好。

3 个答案:

答案 0 :(得分:3)

刚刚交换

for(j=0;j<NUM;j++) 
for(k=0;k<NUM;k++) 

for(k=0;k<NUM;k++) 
for(j=0;j<NUM;j++) 

我有43倍的加速。就像你说的,改善缓存局部性。

甚至可以通过阻止(即交换

)来削减几毫秒
for(j=0;j<NUM;j++) 
  for(j=0;j<NUM;j++) 
    for(k=0;k<NUM;k++) 

通过

for(int i0=0; i0<NUM; i0+=BLK)
  for(int k0=0; k0<NUM; k0+=BLK)
    for(int j0=0; j0<NUM; j0+=BLK)
      for(int i=i0, ix=i0+BLK; i<ix; ++i)
        for(int k=k0, kx=k0+BLK; k<kx; ++k)
          for(int j=j0, jx=j0+BLK; j<jx; ++j)

(我最好的选择是#define BLK 256,但是YMMV)。

澄清:这是@Adriano引用的链接的答案,你真的应该在编辑问题之前查看它。

答案 1 :(得分:1)

这取决于您使用的编译器。使用GCC时,您可以使用__builtin_prefetch,当然在请求优化(使用gcc -O3 -mtune=native进行编译)之后。在基准测试后仔细使用它,请参阅this answer(例如在ij循环中,以获取下一行)。

您的代码非常规则,因此可以对编译器使用OpenMP指令。你甚至可以考虑编写一些OpenCL内核来利用你的GPGPU

答案 2 :(得分:1)

矩阵乘法的直接实现不是非常缓存友好的。您被告知的评论可能是指阻塞,它将在块中进行乘法以改善局部性。 Here是一个参考。如果你谷歌用于&#34;缓存块矩阵乘法&#34;你会得到其他的点击。