因此,我正在探索 WebGPU,并认为在其中实现基本神经网络将是一个有趣的练习。对 GPU 着色器编程和神经网络了解甚少,而且我对 WebGPU(w3.org/TR/webgpu 和 w3.org/TR/WGSL)的唯一参考是高度技术性的,这确实使它变得非常有趣。
不管怎样,不知何故,我已经把自己的方式搞乱了,以至于我实际上可以在小型网络上正确地执行前馈和反向传播,而且与我的 js cpu 实现相比,它的速度也非常快,尽管我确信我严重未充分利用硬件。
我已经到了想要尝试更大网络的地步,但在工作组和同步执行方面我有点不知所措。为了保持简单,我将把问题集中在前馈操作上:
目前,我正在调度与神经网络中最宽层相对应的线程数量。这个想法是,每个线程计算当前层中单个神经元的值,然后遇到障碍,然后每个线程一起移动到下一层,如此下去。
问题是,我只有两种设置屏障的方法 - 要么 workgroupBarrier() 要么结束执行并为下一层分派一堆新线程。
第一个的问题是它只能在工作组内工作,而且我只能在性能开始受到影响之前将工作组设置得这么大,因为据我了解,由于需要共享内存,只有单个 CU 可以在工作组上工作。如果我将工作组设置为 256x256,那么它将被切成多个块,单个 CU 必须在其余硬件闲置时进行处理。这限制了我的网络宽度,限制了单个 CU 可以容纳的线程数量,非常蹩脚。
第二个的问题非常明显 - 单独的调度速度很慢,比我测试的障碍慢得多。
现在,我根本不使用工作组共享内存,我想做的就是分派任意数量的线程并设置全局屏障。据我了解,WebGPU 没有全局屏障......除了 storageBarrier ?
即使在阅读了 w3.org 上关于它是什么的 2 句话之后,我仍然不知道它是什么,但我认为它与内存访问同步有关,而不是与全局屏障有关。我确实测试了它,结果是正确的,但是即使我从代码中消除了所有障碍,结果也是正确的,我猜这是 GPU 的 SIMT 执行风格的好处。但是,我不需要它“可能正确”,我需要保证正确,所以我需要一个全局屏障。是 storageBarrier 吗?如果不是的话那是什么?
额外问题 - 为什么工作组和派遣有 3 个维度,为什么不只有一个?
这几天在学习wgpu,有一点比较困惑。当我浏览 wgpu 示例(https://github.com/gfx-rs/wgpu/tree/master/wgpu/examples)时,他们对其着色器使用以下语法:
struct VertexOutput {
@location(0) color: vec4<f32>,
@builtin(position) position: vec4<f32>,
}
Run Code Online (Sandbox Code Playgroud)
但我必须像这样编写我的着色器:
struct VertexOutput {
[[location(0)]] color: vec4<f32>;
[[builtin(position)]] position: vec4<f32>;
};
Run Code Online (Sandbox Code Playgroud)
@比起语法,我更喜欢[[]]语法。我的猜测是,这是我需要在 Cargo.toml 中启用的功能,但我无法找出这是什么功能。因此,如果有人能告诉我如何@在我的 wgsl 着色器中使用语法,我将不胜感激。