将推力设备迭代器转换为裸指针

4

我正在考虑以下简单代码,其中我正在将 thrust::host_vector<int>::iterator h_temp_iterator = h_temp.begin();thrust::device_vector<int>::iterator d_temp_iterator = d_temp.begin(); 转换为原始指针。

为此,我将 &(h_temp_iterator[0])&(d_temp_iterator[0]) 分别传递给函数和内核。前者(CPU情况)编译通过,后者(GPU情况)没有。这两种情况从原则上讲应该是对称的,因此我不理解错误消息的原因,它是:

Error   1   error : no suitable conversion function from "thrust::device_ptr<int>" to "int *" exists    

配置如下:
  1. Windows 7Visual Studio 2010CUDA 7.5,编译目标架构为3.5
  2. Windows 10Visual Studio 2013CUDA 8.0,编译目标架构为5.2

CODE

#include <thrust\host_vector.h>
#include <thrust\device_vector.h>

__global__ void testKernel(int *a, const int N)
{
    int i = threadIdx.x;

    if (i >= N) return;

    a[i] = 2;
}

void testFunction(int *a, const int N)
{
    for (int i = 0; i < N; i++) a[i] = 2;
}

int main()
{
    const int N = 10;

    thrust::host_vector<int> h_temp(N);
    thrust::device_vector<int> d_temp(N);

    thrust::host_vector<int>::iterator h_temp_iterator = h_temp.begin();
    thrust::device_vector<int>::iterator d_temp_iterator = d_temp.begin();

    testFunction(&(h_temp_iterator[0]), N);
    testKernel<<<1, N>>>(&(d_temp_iterator[0]), N);

    for (int i = 0; i < N; i++) printf("%i %i\n", i, h_temp[i]);

    return 0;
}

1
这只是一个非常轻微的变化,不是吗?https://dev59.com/omgu5IYBdhLWcg3wv5Ya - talonmies
2
在 thrust 标签基础的类型模型(原始模型)中,任何设备内存都由 thrust::device_ptr 表示。它具有指针语义,但不是指针,这有助于强制执行主机/设备指针类型安全性。在上面的代码中,迭代器会衰减为 device_ptr 而不是指针。您必须进行转换以获取原始指针,以便将其传递给设备代码。 - talonmies
谢谢您,talonmies,为您不懈的帮助。我已经解决了这个问题。您想发表一个答案吗? - Vitality
如果你愿意的话,你可以自己写一个。我会点赞的。 - talonmies
谢谢。我已经上传了一个带有完全可用代码的答案。 - Vitality
这是一个问题和答案的示例,最好不要使用MCVE。在我看来,它只会占用屏幕空间,而仅凭内核调用一行代码就可以清楚地解决问题。 - einpoklum
2个回答

5

根据talonmies的评论,解决方案是传递

thrust::raw_pointer_cast(&d_temp_iterator[0])

而不是

&d_temp_iterator[0]

在下面,是完全可用的代码。
#include <thrust\host_vector.h>
#include <thrust\device_vector.h>

__global__ void testKernel(int *a, const int N)
{
    int i = threadIdx.x;

    if (i >= N) return;

    a[i] = 2;

    printf("GPU %i %i\n", i, a[i]);
}

void testFunction(int *a, const int N)
{
    for (int i = 0; i < N; i++) {
        a[i] = 2;
        printf("CPU %i %i\n", i, a[i]);
    }
}

int main()
{
    const int N = 10;

    thrust::host_vector<int> h_temp(N);
    thrust::device_vector<int> d_temp(N);

    thrust::host_vector<int>::iterator h_temp_iterator = h_temp.begin();
    thrust::device_vector<int>::iterator d_temp_iterator = d_temp.begin();

    int *temp = thrust::raw_pointer_cast(&d_temp_iterator[0]);

    testFunction(&(h_temp_iterator[0]), N);
    testKernel<<<1, N>>>(temp, N);

    return 0;
}

4

如果您使用thrust,另一个更美观的解决方案是使用data()获取指针并将其转换为原始指针:

thrust::raw_pointer_cast(d_temp_iterator.data())

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