使用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__内存在不定期访问时也可能会出现问题。
答案 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__不是一回事。你可以从const
和c
的变量定义中消除ci
声明,但我认为有它可以帮助编译器实现你想要的。