Cuda “什么可能导致?”;“未定义的行为”;在这个并行GPU代码中?
假设core1和core2尝试将变量a和b写入同一内存位置 这里如何解释UBCuda “什么可能导致?”;“未定义的行为”;在这个并行GPU代码中?,cuda,undefined-behavior,Cuda,Undefined Behavior,假设core1和core2尝试将变量a和b写入同一内存位置 这里如何解释UB 我们不知道a或b是否写入该内存位置(作为最后一个操作) 我们甚至不知道那里写的是什么(垃圾) 甚至目标内存地址也可能计算错误(segfault?) 一些逻辑门产生错误的电流,CPU会自行禁用 CPU的频率信息变得损坏,并高度超频(并自行中断) 我可以假设只有第一个选项对所有CPU(和GPU)供应商有效吗 我刚刚将下面的代码转换成并行GPU代码,它似乎工作正常 通用代码: for (j=0; j<YRES/CE
- 我们不知道a或b是否写入该内存位置(作为最后一个操作)
- 我们甚至不知道那里写的是什么(垃圾)
- 甚至目标内存地址也可能计算错误(segfault?)
- 一些逻辑门产生错误的电流,CPU会自行禁用
- CPU的频率信息变得损坏,并高度超频(并自行中断)
for (j=0; j<YRES/CELL; j++) // this is parallelized
for (i=0; i<XRES/CELL; i++) // this is parallelized
{
r = fire_r[j][i];
g = fire_g[j][i];
b = fire_b[j][i];
if (r || g || b)
for (y=-CELL; y<2*CELL; y++)
for (x=-CELL; x<2*CELL; x++)
addpixel(i*CELL+x, j*CELL+y, r, g, b, fire_alpha[y+CELL][x+CELL]);
//addpixel accesses neighbour cells' informations and writes on them
//and makes UB
r *= 8;
g *= 8;
b *= 8;
for (y=-1; y<2; y++)
for (x=-1; x<2; x++)
if ((x || y) && i+x>=0 && j+y>=0 && i+x<XRES/CELL && j+y<YRES/CELL)
{
r += fire_r[j+y][i+x];
g += fire_g[j+y][i+x];
b += fire_b[j+y][i+x];
}
r /= 16;
g /= 16;
b /= 16;
fire_r[j][i] = r>4 ? r-4 : 0; // UB
fire_g[j][i] = g>4 ? g-4 : 0; // UB
fire_b[j][i] = b>4 ? b-4 : 0;
}
for(j=0;j对于上述代码,第一个选项是唯一可能的选项。基本上,如果您假设有足够的线程/处理器并行执行所有循环,则内部嵌套循环(x
和y循环)将具有不确定的值
例如,如果我们只考虑
r += fire_r[j+y][i+x];
截面,在
fire\r[j+y][i+x]处的值
可以是原始循环,也可以是同一循环的另一个实例在另一个线程中完成的结果。对于上面的代码,第一个选项是唯一可能的选项。基本上,如果您假设有足够的线程/处理器并行执行所有循环,那么内部嵌套循环(x和y的值将不确定
例如,如果我们只考虑
r += fire_r[j+y][i+x];
第节中,
fire_r[j+y][i+x]
处的值可以是原始值,也可以是同一循环的另一个实例在另一个线程中完成的结果。在xf86和xf86_64体系结构上,这意味着我们不知道a或b是否写入该内存位置(作为最后一个操作),因为加载/存储操作是32(对于这两个)或64位(仅xf86_64)内存对齐的数据类型是原子的
在其他架构上,通常我们甚至不知道那里写的是什么(垃圾)是一个有效的答案——当然在RISC架构上,我目前不知道GPU上写的是什么
请注意,代码工作的事实并不意味着它是正确的,在99%的情况下,它是诸如“存在编译器错误,代码在上一版本之前一直工作”或“代码在开发机器上工作。选择用于生产的服务器已损坏”之类的句子的来源:
编辑:
在NVidia GPU上,我们有弱有序的内存模型。在中没有明确说明存储操作是原子的。写入操作来自同一个线程,因此并不意味着加载/存储操作是原子的。在xf86和xf86_64体系结构上,这意味着我们不知道a或b是否写入该内存位置(作为最后一个操作),因为32位(两者)或64位(仅限xf86_64)内存对齐的数据类型的加载/存储操作是原子的 在其他架构上,通常我们甚至不知道那里写的是什么(垃圾)是一个有效的答案——当然在RISC架构上,我目前不知道GPU上写的是什么 请注意,代码工作的事实并不意味着它是正确的,在99%的情况下,它是诸如“存在编译器错误,代码在上一版本之前一直工作”或“代码在开发机器上工作。选择用于生产的服务器已损坏”之类的句子的来源: 编辑:
在NVidia GPU上,我们有弱有序的内存模型。在中没有明确说明存储操作是原子的。写入操作来自同一个线程,因此这并不意味着加载/存储操作是原子的。当我看到标题时,我直接想回答未定义的
行为
:p您的行为到底是什么问题?如何定义“未定义的行为”通常是定义的?或者这是专门针对某个GPU代码的?我需要了解它有多糟糕。我假设第一个选项,但不确定。根据定义,它有多糟糕没有定义。它可能不会杀死你的猫,但没有人保证,因为未定义的行为显然不被认为是你应该做的事情我一直在想。你不会杀死GPU,就像玩crysis:你只是在做合法的操作,顺序非常随意。当我看到标题时,我直接想回答未定义的行为。你的问题是什么?如何定义“未定义的行为”通常是定义的?或者这是专门针对某个GPU代码的?我需要了解它有多糟糕。我假设第一个选项,但不确定。根据定义,它有多糟糕没有定义。它可能不会杀死你的猫,但没有人保证,因为未定义的行为显然不被认为是你应该做的事情我一直在想。你不会杀死GPU,就像玩crysis一样:你只是在做合法的操作,顺序非常随机。“如果我启用优化,它就什么都做不了”“如果我启用优化,它就什么都做不了”