与CPU上的工作方式不同的CUDA操作

与CPU上的工作方式不同的CUDA操作,cuda,Cuda,我试着在CUDA中使用,经过大量调试,我终于注意到主机代码和CUDA之间的基本运算符存在差异 将负浮点值解析为无符号字符会导致字符为零。这不是在主机上编写相同代码时发生的情况。我浪费了几个小时试图调试为什么我的CUDA代码返回与主机上编写的相同代码不同的东西。(除了CUDA memcheck和printf之外,我不知道如何有效地调试CUDA) 在不知道自己在寻找什么的情况下,是否还有其他东西或惯例也容易打破,很难找到,以及上述差异的原因是什么 以下是我用来测试上述行为的代码: 生成文件:

我试着在CUDA中使用,经过大量调试,我终于注意到主机代码和CUDA之间的基本运算符存在差异

将负浮点值解析为无符号字符会导致字符为零。这不是在主机上编写相同代码时发生的情况。我浪费了几个小时试图调试为什么我的CUDA代码返回与主机上编写的相同代码不同的东西。(除了CUDA memcheck和printf之外,我不知道如何有效地调试CUDA)

在不知道自己在寻找什么的情况下,是否还有其他东西或惯例也容易打破,很难找到,以及上述差异的原因是什么


以下是我用来测试上述行为的代码:

生成文件:

    VCC = nvcc

    .PHONY: all clean

    all: cudaTest

    clean: 
        rm -f *o

    cudaTest: cudaTest.o
        $(VCC) -o $@ $^
    cudaTest.o: cudaTest.cu
        $(VCC) -c $^ `
cudaTest.cu

#include <stdlib.h>
#include <stdio.h>
__global__
void cTests(){

    double d = -2;
    float f = -2;
    int i = -2;
    char c = -2;
    printf("%u, %u\n",(unsigned char)d, (unsigned char)(char)d);
    printf("%u, %u\n",(unsigned char)f, (unsigned char)(char)f);
    printf("%u\n",(unsigned char)i);
    printf("%u\n”",(unsigned char)c);
}

int main(int argc, char* argv[]){
    double d = -2;
    float f = -2;
    int i = -2;
    char c = -2;
    printf("CPU:\n");
    printf("%u \n",(unsigned char)d);
    printf("%u \n",(unsigned char)f);
    printf("%u \n",(unsigned char)i);
    printf("%u \n",(unsigned char)c);
    printf("GPU:\n");
    cTests<<<1,1>>>();
    cudaDeviceSynchronize();
}
此外,由于某些原因,CUDA-MEMCHECK行在终端中位于第一位,但在output.txt文件中位于最后。

如图所示,将浮点数转换为整数类型的过程需要经过几个步骤:

C标准第6.3.1.4节对此进行了详细说明,该节规定了从浮点类型到整数类型的转换:

1当实浮点类型的有限值转换为除_Bool以外的整数类型时,小数部分被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为未定义。61)

在您的特定情况下,您具有负浮点值(例如,
-2.0
),并且您正试图将其直接转换为无符号类型。第一步是删除分数部分,留下
-2
,然后:

如果整数部分的值不能用整数类型表示,则行为未定义。61)

-2
不能用无符号整数类型表示,因此行为未定义。我不想试图提供未定义行为(undefined behavior,UB)的叙述,因为它在其他许多地方都有涉及。但一旦出现未定义行为的情况,实现(即编译器)就可以自由(大致)执行任何操作,并且仍然符合标准

因此,暗示CUDA在某种程度上不符合标准,因为它在直接转换为无符号类型时将
-2.0
转换为任何特定值是不明智的

在这种情况下,一个实现(主机编译器)的行为很可能与另一个实现(设备编译器)的行为不匹配。在UB的情况下,这种不匹配不会告诉您任何关于标准遵从性的信息

(FWIW,CUDA目前并不声称符合任何C标准。它受到各种限制,但就本问题而言,我认为这一区别并不重要。)

关于你的问题:“是否有一种保存[原文如此]的方法来执行此操作?”很难回答,因为我在你的问题中没有找到“此操作”的明确定义。想必你想要一份工作。据我所知,这样的转换是“安全的”,不能“溢出”,并且对任何输入都有一个可预测的结果,与实现无关。它不应该导致UB

所以我怀疑你想做的是先将其转换为有符号整数,然后再转换为无符号整数对于该过程的最后一步(从有符号到无符号的转换),行为应该是可预测的。我不确定从任意浮点数到有符号整数的转换是否符合您对“此操作”的定义(请重新阅读此答案中的第一个引号),但您尚未给出“此操作”的明确定义。

如图所示,将浮点数转换为整数类型的过程需要经过几个步骤:

C标准第6.3.1.4节对此进行了详细说明,该节规定了从浮点类型到整数类型的转换:

1当实浮点类型的有限值转换为除_Bool以外的整数类型时,小数部分被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为未定义。61)

在您的特定情况下,您具有负浮点值(例如,
-2.0
),并且您正试图将其直接转换为无符号类型。第一步是删除分数部分,留下
-2
,然后:

如果整数部分的值不能用整数类型表示,则行为未定义。61)

-2
不能用无符号整数类型表示,因此行为未定义。我不想试图提供未定义行为(undefined behavior,UB)的叙述,因为它在其他许多地方都有涉及。但一旦出现未定义行为的情况,实现(即编译器)就可以自由(大致)执行任何操作,并且仍然符合标准

因此,暗示CUDA在某种程度上不符合标准,因为它在直接转换为无符号类型时将
-2.0
转换为任何特定值是不明智的

在这种情况下,一个实现(主机编译器)的行为很可能与另一个实现(设备编译器)的行为不匹配。在UB的情况下,这种不匹配不会告诉您任何关于标准遵从性的信息

(FWIW,CUDA目前并不声称符合任何C标准。它受到各种限制,但就本问题而言,我认为这一区别并不重要。)

关于你的问题:“是否有一种保存[原文如此]的方法来执行此操作?”很难回答,因为我在你的问题中没有找到“此操作”的明确定义。大概是吧
CPU:
254 
254 
254 
254 
GPU:
0, 254
0, 254
254
254
”========= CUDA-MEMCHECK
========= ERROR SUMMARY: 0 errors