CUDA Thrust算子GMEM访问:ctor数据副本与ctor dev ptr arg

时间:2016-06-14 20:52:12

标签: cuda global-variables thrust

我有两种方法可以让我的推力函子访问全局不可向量化的非均匀访问的只读状态。不幸的是,内核执行时间有100倍的差异。为什么我的两个策略会有任何不同?

更一般地说:是否有一种规范的方法可以提供一个可以访问这些全局变量的推力函子?

我的第一种方法是将我的全局数据副本放入仿函数中。推力机械似乎在设备上执行上传和缓存:

// functor containing a copy of array dependency
template<size_t BARSIZE>
struct foo1_func
{
  __align__(16) float bar[BARSIZE];
  foo1_func(float _bar[BARSIZE]) { memcpy(bar,_bar,BARSIZE*sizeof(float)); }
  __host__ __device__ operator()(float &t) { t = do_something(t, bar); }
}

使用thrust :: for_each ...

调用
// assuming barData is a float[]
foo<N>(barData);

我的第二种方法是使用thrust :: copy自行上传到设备,然后将上传数据的设备内存指针传递给我的仿函数。这种方法看起来要慢得多:

// functor containing device pointers to array in GMEM
struct foo2_func
{
  float *bar;
  foo2_func(float* _bar) { bar = bar; }
  __host__ __device__ operator()(float &t) { t = do_something(t, bar); }
}

使用thrust :: for_each ...

调用
// assuming d_bar is a thrust::device_vector
foo(thrust::raw_pointer_cast(d_bar.data()));

链接到说明感兴趣的规范或独特仿函数模式的来源。

1 个答案:

答案 0 :(得分:1)

使用第一种方法,您实际上是通过将struct bar作为内核函数参数传递给整个数组foo1_func

__global__ void kernel_generated_by_thrust(struct foo_func f, ...) {
  float x = f.bar[3];
  ...
}

如果bar的大小足够小以便放入寄存器,则随机访问bar实际上是对寄存器的随机访问。

但是你的第二种方式只通过结构传递了一个全局内存指针。因此,随机访问bar是对全局内存的随机访问。

这就是为什么第二种方式要慢得多。

两种方式都有其用例。您可以选择其中一个,具体取决于您希望实现的目标,bar的大小以及您希望在缓存bar时花费多少注册。