cuda thrust :: for_each with thrust :: counting_iterator

时间:2016-10-05 15:33:19

标签: c++ cuda thrust

我是CUDA和推力的新手。当提供counting_iterator时,我似乎无法使thrust :: for_each算法工作。 这是我的简单仿函数:

struct print_Functor {
    print_Functor(){}
    __host__ __device__
    void operator()(int i)
    {
        printf("index %d\n", i);
    }
}; 

现在,如果我用预先填充序列的主机向量调用它,它可以正常工作:

    thrust::host_vector<int> h_vec(10);
    thrust::sequence(h_vec.begin(),h_vec.end());
    thrust::for_each(h_vec.begin(),h_vec.end(), print_Functor());

但是,如果我尝试使用thrust :: counting_iterator执行此操作,则会失败:

    thrust::counting_iterator<int> first(0);
    thrust::counting_iterator<int> last = first+10;
    for(thrust::counting_iterator<int> it=first;it!=last;it++)
        printf("Value %d\n", *it);
    printf("Launching for_each\n");
    thrust::for_each(first,last,print_Functor());

我得到的是for循环正确执行,但for_each失败并显示错误消息:

   after cudaFuncGetAttributes: unspecified launch failure

我尝试通过使迭代器类型为模板参数来实现此目的:

thrust::for_each<thrust::counting_iterator<int>>(first,last, print_Functor());

但结果相同。

为了完整起见,我从MATLAB mex文件(64位)中调用它。

我已经能够使用其他推力算法来处理计数迭代器(例如,thrust :: reduce会得到正确的结果)。

作为一个新手,我可能做了一些非常愚蠢的事情并且遗漏了一些明显的东西 - 任何人都可以帮忙吗?

感谢您的评论到目前为止。到目前为止,我已接受了评论。工作的例子(在Matlab之外)工作正常并产生输出,但是如果这被制成一个mex文件,它仍然无法工作 - 第一次根本不产生输出,第二次只产生与以前相同的错误信息(仅通过重新编译修复,当它返回到无输出时)。

然而,即使在DOS下,它也没有从thrust :: for_each执行仿函数。这是一个完整的例子:

#include <thrust/for_each.h>
#include <thrust/iterator/counting_iterator.h>

struct sum_Functor {
    int *sum;
    sum_Functor(int *s){sum = s;}
    __host__ __device__
    void operator()(int i)
    {
        *sum+=i;
        printf("In functor: i %d sum %d\n",i,*sum);
    }

};

int main(){

    thrust::counting_iterator<int> first(0);
    thrust::counting_iterator<int> last = first+10;
    int sum = 0;
    sum_Functor sf(&sum);
    printf("After constructor: value is %d\n", *(sf.sum));
    for(int i=0;i<5;i++){
        sf(i);
    }

    printf("Initiating for_each call - current value %d\n", (*(sf.sum)));
    thrust::for_each(first,last,sf);

    cudaDeviceSynchronize();
    printf("After for_each: value is %d\n",*(sf.sum));
}

这是在DOS提示符下编译的:

nvcc -o pf pf.cu

产生的输出是:

After constructor: value is 0
In functor: i 0 sum 0
In functor: i 1 sum 1
In functor: i 2 sum 3
In functor: i 3 sum 6
In functor: i 4 sum 10
Initiating for_each call - current value 10
After for_each: value is 10

换句话说,仿函数重载的operator()是从for循环中正确调用的,但是从未被thrust :: for_each算法调用。使用计数迭代器时,让for_each执行函子的唯一方法是省略成员变量。

(我应该补充说,经过多年使用纯Matlab,我的C ++非常生疏,所以我可能会遗漏一些明显的东西......)

1 个答案:

答案 0 :(得分:1)

在你的评论中,你说你希望你的代码在主机端执行。

错误代码&#34;未指定的启动失败&#34;以及您的仿函数被定义为主机 设备的事实让我觉得推力想要在您的设备

您可以添加执行策略以确定代码的执行位置吗?

替换:

thrust::for_each(first,last,sf);

thrust::for_each(thrust::host, first,last,sf);

为了能够在GPU上运行,必须在设备内存上分配结果(通过cudaMalloc),然后将其复制回主机。

#include <thrust/host_vector.h>
#include <thrust/sequence.h>
#include <thrust/for_each.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/execution_policy.h>

struct sum_Functor {
    int *sum;
    sum_Functor(int *s){sum=s;}
    __host__ __device__
    void operator()(int i)
    {
        atomicAdd(sum, 1);
    }
};

int main(int argc, char**argv){


    thrust::counting_iterator<int> first(0);
    thrust::counting_iterator<int> last = first+atoi(argv[1]);
    int *d_sum;
    int h_sum = 0;

    cudaMalloc(&d_sum,sizeof(int));
    cudaMemcpy(d_sum,&h_sum,sizeof(int),cudaMemcpyHostToDevice);

    thrust::for_each(thrust::device,first,last,sum_Functor(d_sum));

    cudaDeviceSynchronize();
    cudaMemcpy(&h_sum,d_sum,sizeof(int),cudaMemcpyDeviceToHost);
    printf("sum = %d\n", *h_sum);
    cudaFree(d_sum);

}

代码更新:要在您的设备上获得正确的结果,您必须使用原子操作。