【问题标题】:nvcc compiler not optimizingnvcc 编译器未优化
【发布时间】:2014-06-27 17:45:36
【问题描述】:

为什么编译器不做一些可以在内核中完成的琐碎优化?我有以下矩阵乘法代码:

__global__ void matrixMultiply(float * A, float * B, float * C,
        int numARows, int numAColumns,
        int numBRows, int numBColumns,
        int numCRows, int numCColumns) {

    int n=numAColumns;
    int Row=blockIdx.x*blockDim.x+threadIdx.x;
    int Col=blockIdx.y*blockDim.y+threadIdx.y;
    if((Row<numCRows) && (Col<numCColumns)){
        for(int k=0;k<n;++k){
                    C[Row*numCColumns+Col]+=
                        A[Row*numAColumns+k]*B[k*numBColumns+Col];
        }
    }   
}

如果我使用时间寄存器Cvalue 来存储总和,该示例会更快:

__global__ void matrixMultiply(float * A, float * B, float * C,
        int numARows, int numAColumns,
        int numBRows, int numBColumns,
        int numCRows, int numCColumns) {

    int n=numAColumns;
    int Row=blockIdx.x*blockDim.x+threadIdx.x;
    int Col=blockIdx.y*blockDim.y+threadIdx.y;
    if((Row<numCRows) && (Col<numCColumns)){
        float Cvalue=0;
        for(int k=0;k<n;++k){
            Cvalue+=A[Row*numAColumns+k]*B[k*numBColumns+Col];
        }
        C[Row*numCColumns+Col]=Cvalue;
    }   
}

在最后一种情况下,C 的全局内存只被访问一次,而在第一种情况下,它在循环中被多次访问。这种优化通常不是由编译器完成的吗?在我的测试中,这两个代码的性能差异大约为 30%,我正在做 nvcc -O3 ...

【问题讨论】:

  • 代码不一样。我想你想要C[Row*numCColumns+Col]+= 而不是C[Row*numCColumns+Col]=
  • 对不起,是的...我更正了。
  • 由于C在计算过程中可能被不同的线程访问,所以代码会不一样。
  • 在第一个例子中你也没有将 C 归零。
  • @Dave:由于没有障碍,其他线程可能会做什么是无关紧要的。真正的问题是C 可能与AB 重叠(或与矩阵相同),这使得这两个例程非常不同。

标签: c optimization compiler-construction nvcc


【解决方案1】:

由于C 未声明为__restrict__,编译器无法知道C 是否与AB 是同一矩阵,因此无法执行上述优化。当我改为使用float* __restrict__ C 时,两者的时间几乎相同。谢谢克里斯·多德。

【讨论】:

  • 标准C使用restrict; __restrict__ 完全是另一回事。或者,更确切地说,它可能是完全不同的东西。总的来说,你最好使用标准名称而不是非标准的、可能特定于编译器的扩展。
猜你喜欢
  • 2017-09-28
  • 2017-04-16
  • 2020-12-10
  • 2010-10-05
  • 2011-11-07
  • 1970-01-01
  • 2016-09-27
  • 2016-09-26
  • 2014-02-21
相关资源
最近更新 更多