具有全局内存的Cuda内核与具有恒定内存的Cuda内核

时间:2014-03-04 20:27:04

标签: memory cuda constants global

我有两个用于进行矩阵乘法的内核,一个使用全局内存,第二个内核使用常量内存。我想使用Cuda分析器来测试两个内核的速度。

我在1.3设备和2.0设备上都进行了测试。由于在这些设备上使用缓存作为全局内存,我期望内核具有恒定内存以便在1.3设备上更快并且全局内存内核在2.0设备上更快但我发现在两个设备中全局内存内核是比较快的。这是由于内存在全局内存上的合并吗?如果是这样有一种方法可以使常量内核更快?

我使用80x80的矩阵和16的块大小。

这是全局内存内核

__global__ void MatMulGlobKernel(const Matriz A, const Matriz B, Matriz C) {

float Cvalor = 0;
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;

if(fil > A.height || col > B.width) return;

for (int e = 0; e < A.width; ++e)
Cvalor += A.valores[row * A.width + e] * B.valores[e * B.width + col];

C.valores[row * C.width + col] = Cvalor;
}

A.valores,B.valores和C.valores居于全球记忆中。

现在这里是常量内存内核。

__global__ void MatMulConstKernel(const Matriz A, const Matriz B, Matriz C) {

float Cvalor = 0;
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;

if(fil > A.height || col > B.width) return;

for (int e = 0; e < A.width; ++e)
Cvalor += A_const_valores[row * A.width + e] * B_const_valores[e * B.width + col];

C.valores[row * C.width + col] = Cvalor;
}

A_const_valores和B_const_valores驻留在常量内存中,而C.valores驻留在全局内存中。

这是1.3设备(Tesla M1060)的分析器结果

Const内核101.70us

全局内核51.424us

和2.0设备(GTX 650)

Const内核178.05us

全球内核58.144us

1 个答案:

答案 0 :(得分:1)

矩阵乘法通常有一些组件,其中相邻线程正在从内存中访问相邻值。您的内核具有以这种方式运行的负载:

B.valores[e * B.width + col];

从全局内存中读取时,可以在一个周期内(从L1或L2缓存)向warp提供此负载。是的,这是一个合并的负载。

另一方面,常量存储器每个周期只能提供一个32位数量。因此,常量高速缓存将需要32个周期才能将相同的请求数据传递给warp。

这不是常量内存的典型用例。当 warp中的每个线程请求内存中的相同位置时,最好使用常量内存。

作为一项实验,您可能会看到如果将A矩阵保留在__constant__内存中并将B矩阵保留在全局内存中,您可能会得到什么样的结果。

但是,如果您真的想要快速矩阵乘法,请使用CUBLAS。

相关问题