在CUDA 9.2中,我有类似的东西:
#ifdef __CUDA_ARCH__
struct Context { float n[4]; } context;
#else
typedef __m128 Context;
#endif
struct A { float k[2]; };
struct B { float q[4]; };
struct FTransform : thrust::unary_function<A, B>
{
const Context context;
FTransform(Context context) : context(context){}
__device__ __host__ B operator()(const A& a) const
{
B b{{a.k[0], a.k[1], a.k[0]*context.n[0], a.k[1]*context.n[1]}};
return b;
}
};
void DoThrust(B* _bs, const Context& context, A* _as, uint32_t count)
{
thrust::device_ptr<B> bs = thrust::device_pointer_cast(_bs);
thrust::device_ptr<A> as = thrust::device_pointer_cast(_as);
FTransform fTransform(context);
auto first = thrust::make_transform_iterator(as, fTransform);
auto last = thrust::make_transform_iterator(as + count, fTransform);
thrust::copy(first, last, bs);
}
int main(int c, char **argv)
{
const uint32_t Count = 4;
Context context;
A* as;
B* bs;
cudaMalloc(&as, Count*sizeof(A));
cudaMalloc(&bs, Count*sizeof(B));
A hostAs[Count];
cudaMemcpy(as, hostAs, Count * sizeof(A), cudaMemcpyHostToDevice);
DoThrust(bs, context, as, Count);
B hostBs[Count];
cudaMemcpy(hostBs, bs, Count * sizeof(B), cudaMemcpyDeviceToHost);//crash
return 0;
}
然后,当我稍后调用标准cudaMemcpy()调用结果时,我得到异常“遇到非法内存访问”。
如果我用非推力等效物替换推力代码,则没有错误,一切正常。试图复制到device_vectors等的各种组合我得到了不同的崩溃,似乎试图释放device_ptr由于某种原因 - 所以也许它出于某种原因?
== UPDATE ==
好吧这令人困惑它似乎是由于我实际更复杂的情况下的仿函数FTransform上下文成员变量。具体如下:
struct FTransform : thrust::unary_function<A, B>
{
#ifdef __CUDA_ARCH__
struct Context { float v[4]; } context;
#else
__m128 context;
#endif
...
};
所以我猜这是一个对齐问题,某种方式=&gt;事实上它是,因为这是有效的:
#ifdef __CUDA_ARCH__
struct __align__(16) Context { float v[4]; } context;
#else
__m128 context;
#endif
答案 0 :(得分:-2)
解决方案是确保如果在复制到GPU的推力仿函数成员(例如__m128 SSE类型)中使用对齐类型,则在NVCC的CPU和GPU代码构建过程中将它们定义为对齐 - 而不是意外地假设,即使某种类型似乎自然地与另一种类型相对应,它也可以正常,因为否则很难理解可能发生的事情。
所以例如在这样的代码中需要_ align _(16):
struct FTransform : thrust::unary_function<A, B>
{
#ifdef __CUDA_ARCH__
struct __align__(16) Context { float v[4]; } context;
#else
__m128 context;
#endif
FTransform(Context context) : context(context){}
__device__ __host__ B operator()(const A& a) const; // function makes use of context
};