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

CUDA vs英特尔AVX/SSE矢量和性能问题,cuda,simd,intrinsics,Cuda,Simd,Intrinsics,首先,我是CUDA的新手,我正在努力学习,所以可能我做错了什么。我想比较CUDA性能与使用Intel Intrinsic实现的等效函数,期望CUDA能产生更好的结果 但令我惊讶的是,这不是我所看到的。我的函数非常简单,我只需添加两个向量并将结果存储在第三个向量中。我的CUDA代码是最基本的,在设置函数中我有: void cudaAddVectors(float* vectorA, float* vectorB, float* sum, int numElements) { // // Alloc

首先,我是CUDA的新手,我正在努力学习,所以可能我做错了什么。我想比较CUDA性能与使用Intel Intrinsic实现的等效函数,期望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);
}

我对Intel版本和CUDA对不同大小的向量求和进行了计时,并验证两者都产生了准确的结果。对于CUDA调用,我只对deviceSumLink调用进行计时,而不是内存设置和所有操作,但不管调用内核的方法是什么,Intel intrinsics版本(使用8元素数组)只是将CUDA从水中抽出来。基本上,英特尔SIMD版本的函数快了10倍

我没有想到这一点,所以我把这归因于我在CUDA是一个完全的新手。那么我做错了什么?我想CUDA应该在这些方面快得多,我想我一定没有正确使用它

如果你有一些见解,我将感谢你的评论


谢谢

仅使用1个块或每个块使用1个线程来添加向量不会充分利用GPU。而且它们不会对大的向量起作用

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

__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];
    }
}
全局无效
矢量添加(常量浮点*A、常量浮点*B、浮点*C、整数)
{
int i=blockDim.x*blockIdx.x+threadIdx.x;
如果(i
并使用以下线程/块设置调用它

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

vectorAdd<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, numElements);
int-threadsPerBlock=256;
int blocksPerGrid=(numElements+threadsPerBlock-1)/threadsPerBlock;
矢量加法(d_A,d_B,d_C,numElements);
请参考此CUDA示例了解更多详细信息


忘记添加了,我正在使用2.3 GHz Intel Core i7和NVidia GeForce GT 650M的MacBookPro视网膜上运行此功能。您是说您的基准测试是在使用8个浮点数的阵列上进行的吗?(即numElements=8)?numElements可以是8的任意倍数,并且向量是浮点,是的。英特尔希望内存与32字节的边界对齐,这样它们就对齐了。这不是我所要求的。让我再试一次。对于引用的“大约快10倍!”,您使用的
numElements
的值是多少。是的,在这个特殊情况下是的……我尝试了8的不同倍数,我看到了一些奇怪的结果,例如,对于intel,800个元素产生0.001028毫秒,对于CUDA产生0.013893毫秒。然后8000个元素中英特尔为0.009781,CUDA为0.008457,然后80000个元素中英特尔为0.105219,CUDA为0.006614(?),那么,我缺少什么呢?为什么80000比8000快?谢谢你的帮助
__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);