CUDA与英特尔AVX / SSE矢量和性能问题

时间:2013-10-13 19:26:20

标签: cuda simd intrinsics

首先,我是CUDA的新手,我正在努力学习,所以也许我做错了什么。我想比较CUDA性能与英特尔内在函数实现的等效函数,期望CUDA能产生更好的结果。

令我惊讶的是,那不是我所看到的。我的功能非常简单,我只需添加两个向量并将结果存储在第三个向量中。我的CUDA代码是基本的,在我的设置函数中:

void cudaAddVectors(float* vectorA, float* vectorB, float* sum, int numElements)
{
//
// Allocate the memory on the device
//
float* dvA;
float* dvB;
float* dvC;

cudaMalloc((void**)&dvA, numElements * sizeof(float));
cudaMalloc((void**)&dvB, numElements * sizeof(float));
cudaMalloc((void**)&dvC, numElements * sizeof(float));

//
// Copy the host vectors to device vectors
//
cudaMemcpy(dvA, vectorA, numElements * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(dvB, vectorB, numElements * sizeof(float), cudaMemcpyHostToDevice);

//
// Perform the sum on the device and time it
//
deviceSumLink(dvA, dvB, dvC, numElements);

//
// Now get the results back to the host
//
cudaMemcpy(sum, dvC, numElements * sizeof(float), cudaMemcpyDeviceToHost);

// Cleanup and go home
cudaFree(dvA);
cudaFree(dvB);
cudaFree(dvC);

}

然后使用块或线程运行设备代码,如下所示:

void deviceSumLink(float* a, float* b, float* c, int numElements)
{
    //deviceSum<<<numElements, 1>>>(a,b,c);
    deviceSumThreads<<<1, numElements>>>(a,b,c);
}

设备上运行的实际代码:

__global__ void deviceSum(float* a, float* b, float* c)
{
    int index = blockIdx.x;
    c[index] = a[index] + b[index];
}

__global__ void deviceSumThreads(float* a, float* b, float* c)
{
    int index = threadIdx.x;
    c[index] = a[index] + b[index];
}

我计算了英特尔版本和CUDA总结不同大小的向量并验证两者都能产生准确的结果。对于CUDA调用,我只计时deviceSumLink调用,而不是内存设置和所有内容,但无论调用内核的方法如何,英特尔内在函数版本(使用8元素数组)只是抽出CUDA水。基本上,该功能的英特尔SIMD版本速度提高了10倍!

我没想到这一点,所以我认为这是我在CUDA中的一个完整的新手。那么我做错了什么?我认为CUDA应该在这些事情上要快得多,我想我一定不能正确使用它。

如果你有一些见解,我会很感激你的评论!

THX!

1 个答案:

答案 0 :(得分:1)

每个块仅使用1个块或1个线程来添加向量将无法充分利用GPU。由于the limitation of thread size per block and block size,它们不适用于大型矢量。

要正确添加两个大型向量并获得最大性能,您需要一个像这样的内核

__global__ void
vectorAdd(const float *A, const float *B, float *C, int numElements)
{
    int i = blockDim.x * blockIdx.x + threadIdx.x;

    if (i < numElements)
    {
        C[i] = A[i] + B[i];
    }
}

并使用以下线程/块设置

调用它
int threadsPerBlock = 256;
int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock;

vectorAdd<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, numElements);

有关详细信息,请参阅此CUDA示例。

http://docs.nvidia.com/cuda/cuda-samples/#vector-addition