CUDA C与Thrust,我有什么遗漏吗?

4
我刚开始学习CUDA编程。我浏览了一些简单的CUDA C范例,一切都顺利进行。然而!突然发现了Thrust!我认为自己对C++函数对象很熟悉,但是对于CUDA C和Thrust之间的区别感到惊讶。
我觉得很难相信。
__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, %f\n", 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是否自动处理线程索引计算?
谢谢您的时间。如果这些问题很愚蠢,请原谅,但我发现我所看到的例子从描述为Model T转换为M3是难以置信的。
1个回答

6
大体上是:当然可以。Thrust是一个库,就像其他库一样,旨在使编程更容易。它的优点在于避免了所有明确的CUDA代码,对于其他程序员来说看起来很奇怪,并提供友好的类似于C++的接口。
Thrust使用GPU,但不仅仅是GPU。它执行与您编写自己的代码相同的操作,即用于分配内存、复制、设置网格和块大小的C/C++代码……然后调用GPU执行内核。
对于那些不想深入了解低级CUDA内容,但想利用GPU并行性解决简单(但频繁出现的)问题,如向量操作的人来说,这是一个不错的选择。

那么 thrust::transform 函数会调用我的 square 内核吗?它如何知道如何分配线程? - Tyler Jandreau
2
是的,它会调用您的函数对象,作为它在“引擎盖下”创建的内核的一部分。Thrust是一个开源库;您可以自行检查它。还有GPU性能分析工具可用于确认Thrust确实正在使用GPU。关于线程分配,将一个线程分配给每个输出元素是CUDA编程中常见的策略,当创建大量输出时。查看您的函数对象和整个算法,我观察到输入和输出之间存在1:1的关系(通常适用于transform),因此每个数据元素一个线程是有意义的。 - Robert Crovella

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接