Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
cuda代码是否跳过逻辑表达式中不必要子句的执行? 普通C++,如果我说下面的话,它是安全的,因为第三个子句将跳过执行。我只是想知道cuda内核代码是否也有这个属性,或者考虑到最大化并行性,它没有这个属性 int x[100] = {...}, i = -1; if (i < 0 || i >= 100 || x[i] == 0) { // do something. } intx[100]={…},i=-1; 如果(i=100 | | x[i]==0){ //做点什么。 }_Cuda - Fatal编程技术网

cuda代码是否跳过逻辑表达式中不必要子句的执行? 普通C++,如果我说下面的话,它是安全的,因为第三个子句将跳过执行。我只是想知道cuda内核代码是否也有这个属性,或者考虑到最大化并行性,它没有这个属性 int x[100] = {...}, i = -1; if (i < 0 || i >= 100 || x[i] == 0) { // do something. } intx[100]={…},i=-1; 如果(i=100 | | x[i]==0){ //做点什么。 }

cuda代码是否跳过逻辑表达式中不必要子句的执行? 普通C++,如果我说下面的话,它是安全的,因为第三个子句将跳过执行。我只是想知道cuda内核代码是否也有这个属性,或者考虑到最大化并行性,它没有这个属性 int x[100] = {...}, i = -1; if (i < 0 || i >= 100 || x[i] == 0) { // do something. } intx[100]={…},i=-1; 如果(i=100 | | x[i]==0){ //做点什么。 },cuda,Cuda,编辑: 根据Jack的程序,以下程序运行正常并输出“10”。执行cuda memcheck没有错误 #include <stdio.h> __global__ void test(float *input, float *output, int i, int N) { float c = 10; // NOTE: uncomment this will cause cuda-memcheck to give an error. // c = input[-

编辑:

根据Jack的程序,以下程序运行正常并输出“10”。执行cuda memcheck没有错误

#include <stdio.h>

__global__ void test(float *input, float *output, int i, int N) {
    float c = 10;

    // NOTE: uncomment this will cause cuda-memcheck to give an error.
    // c = input[-1];

    if (i < 0 || i >= N || (c = input[-1])) {
        output[0] = c;
    }
}

int main(void) {

    int i = -1;
    int N = 10;

    float* input;
    float* output;
    float* dev_input;
    float* dev_output;

    input = (float*)malloc(sizeof(float) * N);
    output = (float*)malloc(sizeof(float));
    for (int j = 0; j < N; j++) {
      input[j] = 2.0f;
    }
    output[0] = 3.0f;

    cudaMalloc((void**)&dev_input,sizeof(float) * N);
    cudaMalloc((void**)&dev_output,sizeof(float));

    cudaMemcpy(dev_input,input,sizeof(float) * N,cudaMemcpyHostToDevice);
    cudaMemcpy(dev_output,output,sizeof(float),cudaMemcpyHostToDevice);

    test<<<1,1>>>(dev_input,dev_output,i,N);

    cudaMemcpy(output,dev_output,sizeof(float),cudaMemcpyDeviceToHost);

    printf("%f\n", output[0]);
    return 0;
}
#包括
__全局无效测试(浮点*输入,浮点*输出,整数i,整数N){
浮点数c=10;
//注意:取消注释将导致cuda memcheck出现错误。
//c=输入[-1];
如果(i<0 | | i>=N | |(c=input[-1])){
输出[0]=c;
}
}
内部主(空){
int i=-1;
int N=10;
浮点*输入;
浮点*输出;
浮点*dev_输入;
浮点*dev_输出;
输入=(浮点*)malloc(sizeof(浮点)*N);
输出=(float*)malloc(sizeof(float));
对于(int j=0;j
尝试下面的简单代码,其中内核函数尝试访问
输入[-1]
。你会意识到它会被卡住

#include <stdio.h>

__global__ void test(float *input, float *output, int i, int N) {

    if (i < N || input[i] == 0) {
        output[i] = input[i];
    }
}

void main(void) {

    int i = -1;
    int N = 10;

    float* input;
    float* dev_input;
    float* dev_output;

    input = (float*)malloc(sizeof(float));
    input[0] = 2.f;

    cudaMalloc((void**)&dev_input,sizeof(float));
    cudaMalloc((void**)&dev_output,sizeof(float));

    cudaMemcpy(dev_input,input,sizeof(float),cudaMemcpyHostToDevice);

    test<<<1,1>>>(dev_input,dev_output,i,N);
}
#包括
__全局无效测试(浮点*输入,浮点*输出,整数i,整数N){
如果(i
原因可以通过查看反汇编代码来解释

   MOV R1, c[0x1][0x100];                              R1 = c[0x1][0x100]
   NOP;
   MOV R3, c[0x0][0x28];                               R3 = c[0x0][0x28]
   SHL R2, R3, 0x2;                                    R2 = shiftleft(R3)           
   IADD R0, R2, c[0x0][0x20];                          R0 = R2 + 0x2
   LDU R0, [R0];                                       Load the memory addressed by R0 to R0
   FSETP.EQ.AND P0, PT, R0, RZ, PT;                    Predicate register P0 will contain result of test R0 == 0
   ISETP.LT.OR P0, PT, R3, c[0x0][0x2c], P0;           Predicate register P0 will contain result of test P0 || (R3 < c[0x0][0x2c])
@P0 IADD R2, R2, c[0x0][0x24];                         ...
@P0 ST [R2], R0;
   EXIT ;
movr1,c[0x1][0x100];R1=c[0x1][0x100]
否;
MOV R3,c[0x0][0x28];R3=c[0x0][0x28]
shlr2,R3,0x2;R2=移位英尺(R3)
IADD R0,R2,c[0x0][0x20];R0=R2+0x2
LDU R0,[R0];将R0寻址的内存加载到R0
FSETP.EQ.和P0,PT,R0,RZ,PT;谓词寄存器P0将包含测试结果R0==0
ISETP.LT.或P0,PT,R3,c[0x0][0x2c],P0;谓词寄存器P0将包含测试P0的结果(R3

如您所见,无论第一个子句的结果如何,设备都将尝试从全局内存加载数据。

CUDA C/C++编译器在这方面应该遵守


具体而言,对于非过载的
|
&&
操作员,应保持操作顺序和短路方面的语言要求。

谢谢!我试过这个程序,但结论似乎相反,请看我的编辑。我不确定这个答案提出了什么主张或断言,或者它对提出的问题提供了什么答案。然而,由于指出了全局内存负载的存在,所以如果第一个条件(<代码> i<n>代码>)是错误的,我们将考虑是否加载<代码>输入[i] < /代码>。然后,如果第一个条件为真,将考虑<代码>输入[i] < /代码>是否加载。它也将由内核的下一行加载。因此,编译器可以无条件地生成加载。@RobertCrovella我只是想指出,如果(I<0 | | | I>=100 | | x[I]==0){//do something.}
执行OP指示的操作是不安全的。从反汇编的代码中,我可以得出结论,
input[I]
正在无条件加载,从您的评论来看,这似乎也是您的结论。请指出OP查询的任何错误陈述/结论或误解,我将修改/删除我的帖子。我看不出你的代码如何证明
如果(I<0|I>=100|x[I]==0){
是不安全的。对于
I=-1
的输入,即使你的if条件是
if(I
。我猜你是在说你在回答一个问题“它安全吗?”而这不是OP所问的。OP所问的“CUDA是否会评估某些条款?”此外,OP似乎将你的答案解释为OP问题的答案(当然不是),OP的评论和发布编辑中出现的混乱证明了这一点(“结论似乎相反”)@RobertCrovella我已要求SO团队删除此答案。您的反汇编代码看起来与@jackolanten提供的代码不同,它将包含必要的序列点,以防止他观察到的无条件加载。
input[-1]
在您的情况下不是无条件加载的。那么为什么Jack的代码
如果(i
无条件加载?我想不出区别吗?杰克的代码有两种输入方式。要么
i
小于
N
,要么
i
不小于
N
。拿每个案例,一路走完杰克的代码,问自己“will
input[i]
get load?”在这两种情况下,答案都是肯定的。因此编译器可以无条件地加载它。如果
i
不小于