全局数组矢量类型解决方法

时间:2013-03-07 15:16:31

标签: cuda

使用CUDA我正在尝试使用由向量组成的数组进行编译时优化(在我的情况下为int2),但我无法以干净的方式实现此目的。让我们更具体一点,我正在研究一个使用两个常数数组c和w的问题。数组w由浮点数组成,数组c由int2组成。现在,由于这些数组是常量,我希望编译器执行编译时优化,从而有效地优化数组访问。例如,对于以下两个设备函数,编译器展开循环并通过直接用c和w的值替换它来优化数组访问:

__forceinline__ __device__ float someFunction1() {
  const int2  c[9] = {make_int2(0, 0), make_int2(1, 0), make_int2(0, 1), make_int2(-1, 0), make_int2(0, -1),
                      make_int2(1, 1), make_int2(-1, 1), make_int2(-1, -1), make_int2(1, -1)};
  const float w[9] = {4.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/36.0f, 1.0f/36.0f, 1.0f/36.0f, 1.0f/36.0f};
  #pragma unroll
  for (int i = 0; i < 9; ++i) {
    //Do something here, accessing c[i] and w[i]
  }
}

__forceinline__ __device__ float someFunction2() {
  const int2  c[9] = {make_int2(0, 0), make_int2(1, 0), make_int2(0, 1), make_int2(-1, 0), make_int2(0, -1),
                           make_int2(1, 1), make_int2(-1, 1), make_int2(-1, -1), make_int2(1, -1)};
  const float w[9] = {4.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/36.0f, 1.0f/36.0f, 1.0f/36.0f, 1.0f/36.0f};
  #pragma unroll
  for (int i = 0; i < 9; ++i) {
    //Do something here, accessing c[i] and w[i]
  }
}

现在,问题是我不想在每个使用c和w的设备函数中连续声明c和w。我可以全局声明w,但我不允许全局声明c,因为CUDA不允许我在全局变量中调用make_int2构造函数。也就是说,下面的程序给出错误“无法为设备上的非空构造函数或析构函数生成代码”:

//Declaring array c like this is not allowed
__device__ const int2  c[9] = {make_int2(0, 0), make_int2(1, 0), make_int2(0, 1), make_int2(-1, 0), make_int2(0, -1),
                               make_int2(1, 1), make_int2(-1, 1), make_int2(-1, -1), make_int2(1, -1)};
__device__ const float w[9] = {4.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/36.0f, 1.0f/36.0f, 1.0f/36.0f, 1.0f/36.0f};

__forceinline__ __device__ float someFunction() {
  #pragma unroll
  for (int i = 0; i < 9; ++i) {
    //Do something here, accessing c[i] and w[i]
  }
}

我的问题是:如何阻止在访问这些变量的每个函数中声明c和w,并且仍然具有我想要的编译时优化?或者另有说明:是否有一种解决方案可以全局声明一组向量?

N.B。:我知道我可以在全局或__constant__内存中存储c和w,但这不会给我编译时优化。 __constant__内存在不定期访问时也可能会出现问题。

1 个答案:

答案 0 :(得分:1)

我不知道这是否真的能够在编译器优化方面实现您的目标,但是将指针从int转换为int2似乎对我有用:

#include <stdio.h>

  __device__ const int  ci[16] = {0, 0, 1, 0, 0, 1, -1, 0, 0, -1, 1, 1, -1, 1, -1, -1};

  __device__ const int2 *c = (const int2 *)ci;

  __global__ void mykernel(){

  int2 temp = c[1];
  int2 temp1 = c[4];
  printf("c[1].x = %d\n", temp.x);
  printf("c[4].y = %d\n", temp1.y);
  }

int main(){

  mykernel<<<1,1>>>();
  cudaDeviceSynchronize();
  printf("Done\n");
  return 0;
}

请注意,const__ constant__不是一回事。你可以从constc的变量定义中消除ci声明,但我认为有它可以帮助编译器实现你想要的。