我经常注意到,global
设备constant
内存初始化为 0。这是通用规则吗?我在标准中找不到任何东西。
3 回答
不,它没有。例如,我有这个小内核来测试原子添加:
kernel void atomicAdd(volatile global int *result){
atomic_add(&result[0], 1);
}
使用此主机代码(pyopencl + unittest)调用它:
def test_atomic_add(self):
NDRange = (4, 4)
result = np.zeros(1, dtype=np.int32)
out_buf = cl.Buffer(self.ctx, self.mf.WRITE_ONLY, size=result.nbytes)
self.prog.atomicAdd(self.queue, NDRange, NDRange, out_buf)
cl.enqueue_copy(self.queue, result, out_buf).wait()
self.assertEqual(result, 16)
使用我的 CPU 时总是返回正确的值。然而,在 ATI HD 5450 上,返回的值总是垃圾。
如果我记得很清楚,在 NVIDIA 上,第一次运行返回了正确的值,即 16,但对于接下来的运行,值是 32、48 等。它重用了相同的位置,旧值仍然存储在那里。
当我用这一行更正我的主机代码时(将 0 值复制到缓冲区):
out_buf = cl.Buffer(self.ctx, self.mf.WRITE_ONLY | self.mf.COPY_HOST_PTR, hostbuf=result)
在任何设备上一切正常。
据我所知,标准中没有任何句子说明这一点。也许某些驱动程序实现会自动执行此操作,但您不应该依赖它。
我记得有一次我遇到一个缓冲区没有初始化为0的情况,但是我不记得“OS +驱动程序”的设置。
可能正在发生的事情是典型的操作系统甚至不使用现在一天设备内存的 1%。因此,当您启动 OpenCL 时,您很有可能会陷入空白区域。
这取决于您正在开发的平台。正如@DarkZeros 在前面的答案中提到的那样,该规范并不暗示任何事情。请参阅OpenCL 2.1 Spec的第 104 页。
但是,根据我们在 Mali GPU 中的经验,驱动程序会将新分配的缓冲区的所有元素初始化为零。这是第一次接触。后来,随着时间的推移,我们释放了这个缓冲区,它的内存空间被一个新的缓冲区占用,那个内存空间没有初始化为零。“同样,第一次触摸会看到零值。之后,你会看到正常的乱码值。”
希望在这么长时间后这会有所帮助!