CUDA C诉Thrust,我错过什么了吗?



我刚开始学习CUDA编程。我正在浏览一些简单的CUDA C示例,一切都进行得很顺利。然后!突然!推力!我认为自己精通c++函子,但对CUDA CThrust之间的差异感到惊讶

我很难相信

__global__ void square(float *a, int N) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (idx < N) {
        a[idx] = a[idx] * a[idx];
    }
}
int main(int argc, char** argv) {
float *aHost, *aDevice;
const int N = 10;
size_t size = N * sizeof(float);
aHost = (float*)malloc(size);
cudaMalloc((void**)&aDevice, size);
for (int i = 0; i < N; i++) {
    aHost[i] = (float)i;
}
cudaMemcpy(aDevice, aHost, size, cudaMemcpyHostToDevice);
int block = 4;
int nBlock = N/block + (N % block == 0 ? 0:1);
square<<<nBlock, block>>>(aDevice, N);
cudaMemcpy(aHost, aDevice, size, cudaMemcpyDeviceToHost);
for (int i = 0; i < N; i++) {
    printf("%d, %fn", i, aHost[i]);
}
free(aHost);
cudaFree(aDevice);
}

等于

template <typename T>
    struct square {
    __host__ __device__ T operator()(const T& x) const {
        return x * x;
    }
}; 
int main(int argc, char** argv) {
    const int N = 10;
    thrust::device_vector<float> dVec(N);
    thrust::sequence(dVec.begin(), dVec.end());
    thrust::transform(dVec.begin(), dVec.end(), dVec.begin(), square<float>());
    thrust::copy(dVec.begin(), dVec.end(), std::ostream_iterator<float>(std::cout, "n"));
}

我错过了什么吗?上述代码是否在GPU上运行?Thrust是一个很棒的工具,但我怀疑它是否能处理所有繁重的c风格内存管理。

  • Thrust代码是否正在GPU上执行?我怎么知道?
  • Thrust如何消除调用内核的奇怪语法?
  • Thrust实际上是调用内核吗?
  • Thrust是否自动处理线程索引计算?

谢谢你的时间。如果这些问题很愚蠢,我很抱歉,但我发现我所看到的例子从T型车到M3的瞬间转换令人难以置信。

大致来说:当然可以。Thrust是一个库,所以所有这些都是为了使它更容易。它的优点是避免了所有显式CUDA代码,这对其他程序员来说看起来很奇怪,提供了一个友好的类似c++的界面。

Thrust使用GPU,而不是,只是 GPU。如果您编写自己的代码,即C/c++代码分配内存,复制,设置网格和块大小,它会进行相同的操作……然后调用GPU执行内核。

对于那些不想进入低级CUDA的人来说,这是一个很好的选择,但是要在一个简单(但经常)的问题中利用GPU的并行性,比如向量运算。

相关内容

最新更新