环路的Cuda测量

环路的Cuda测量,cuda,measurement,Cuda,Measurement,我在CUDA Fermi GPU上启动了一个非常简单的内核 __global__ void kernel(){ int x1,x2; x1=5; x2=1; for (int k=0;k<=1000000;k++) { x1+=x2; } } \uuuu全局\uuuuu无效内核(){ int-x1,x2; x1=5; x2=1; 对于(int k=0;k,因为编译器消除了死路径。您的代码实际上什么都不做。请查看程序集 如果您确实看到了该值,那么编译器可能刚刚优化了循环

我在CUDA Fermi GPU上启动了一个非常简单的内核

__global__ void kernel(){
int x1,x2;

x1=5;
x2=1;

for (int k=0;k<=1000000;k++)
  {
   x1+=x2;

  }
}
\uuuu全局\uuuuu无效内核(){
int-x1,x2;
x1=5;
x2=1;

对于(int k=0;k,因为编译器消除了死路径。您的代码实际上什么都不做。请查看程序集

如果您确实看到了该值,那么编译器可能刚刚优化了循环,因为它可以在编译时知道该值


当您将寄存器内容写入共享内存时,编译器无法保证结果不会被使用,因此将实际计算该值。换句话说,您计算的值最终必须在某个地方使用或写入内存,否则其计算将被删除。

因为编译器消除了死区路径。你的代码实际上没有做任何事情。看看程序集

如果您确实看到了该值,那么编译器可能刚刚优化了循环,因为它可以在编译时知道该值


当您将寄存器内容写入共享内存时,编译器无法保证结果不会被使用,因此将实际计算该值。换句话说,您计算的值最终必须在某个地方使用或写入内存,否则其计算将被删除。

如前所述,CUDA编译器优化在删除死代码方面非常积极。因为
x2
不参与写入内存的值,所以可以删除它和循环。编译器还将预计算在编译时可以推导的任何结果,因此如果编译器知道循环中的所有常数,它可以计算最终结果并重新执行C用一个常数来表示它

要解决这两个问题,请按如下方式重写代码:

__global__ 
void kernel(int *out, int x0, bool flag)
{
    int x1 = x0, x2 = 1;

    for (int k=0; k<=1000000; k++) {
       x1+=x2;
    }

    if (flag) out[threadIdx.x + blockIdx.x*blockDim.x] = x1;
}
kernel<<<1,512>>>((int *)0, 5, false);
\uuuu全局\uuuu
无效内核(int*out、int x0、bool标志)
{
int-x1=x0,x2=1;

对于(int k=0;k如上所述,CUDA编译器优化在删除死代码方面非常积极。因为
x2
不参与写入内存的值,它和循环可以被删除。编译器还将预计算在编译时可以推导的任何结果,因此如果c知道循环中的所有常数ompiler,它可以计算最终结果并用常量替换

要解决这两个问题,请按如下方式重写代码:

__global__ 
void kernel(int *out, int x0, bool flag)
{
    int x1 = x0, x2 = 1;

    for (int k=0; k<=1000000; k++) {
       x1+=x2;
    }

    if (flag) out[threadIdx.x + blockIdx.x*blockDim.x] = x1;
}
kernel<<<1,512>>>((int *)0, 5, false);
\uuuu全局\uuuu
无效内核(int*out、int x0、bool标志)
{
int-x1=x0,x2=1;
对于(int k=0;k