我对 Halide 有一定的了解,并开始学习使用 CUDA。首先,我运行了 Halide 源代码附带的 halide
cuda_mat_mul
。
我得到了一些合理但不令人印象深刻的时间安排:
CPU, autoschedule, Adams2019: 4.2ms
GPU, autoschedule, Anderson2021: 3.0ms
GPU, manual schedule: 1.2ms
CUBLAS: 0.42ms
这看起来正确吗?我有一个 Nvidia RTX 3050 Ti 笔记本电脑 GPU 和一个酷睿 i5-11400h CPU
camera_pipe
在 GPU 上运行。
它带有 CPU 和 GPU 的时间表。 CMake 文件仅适用于 CPU。我修改它来通过设置进行 CUDA 构建
FEATURES cuda cuda_capability_50
并给予它 CUDA_INCLUDE_DIRS
和 CUDA_LIBRARIES
就像在 cuda_mat_mul
应用程序中一样。
我还添加了
output.copy_to_host();
在process.cpp
。
我记录了以下运行时间:
CUDA (manual): 1270ms
cpu auto_schedule Adams19: 10.5ms
cpu manual: 9.9ms
所以 CUDA 比 CPU 慢得多。
这是一次计时迭代。然后我尝试进行 100 次迭代。
CUDA manual 1st iteration: 1270ms
next 100 iterations: 5.7ms
然后我在 CPU 上尝试了 100 次迭代:
cpu manual: 1st iteration: 10.8ms
next 100 iterations: 5.8ms
cpu auto_schedule (Adams19) 100 iterations: 7ms
为什么第一次GPU迭代这么慢?为什么后续运行在 CPU 和 GPU 上的速度几乎相同? 我验证它正在生成正确的输出图像。我也尝试过设置
input.set_host_dirty();
,但没有什么区别。
我尝试使用
Anderson2021
在 GPU 上进行自动调度,但出现以下错误:
C:\Users\cordo\source\repos\camera_pipe17\out\build\x64-Debug\camera_pipe_auto_schedule.runtime.lib(camera_pipe_auto_schedule.runtime.obj) : error LNK2005: .weak._ZN6Halide7Runtime8Internal13custom_mallocE.default.halide_internal_aligned_alloc already defined in camera_pipe.runtime.lib(camera_pipe.runtime.obj)
还有几个类似的错误。 谢谢
相机管道应用程序的编写是为了利用 CPU 上存在的各种定点指令,而不是 GPU 上的定点指令,因此与大多数其他应用程序相比,GPU 在这方面的表现会非常糟糕。在我的机器上,CPU (i9-9960X) 上为 1.5ms,GPU (RTX 2060) 上为 1.15ms。正如其他人所说,第一次迭代很慢,因为 Halide 初始化 cuda 库并编译所有着色器。
对于 cuda_mat_mul,nvidia 花费了大量工程师时间为每个 GPU 编写优化的矩阵乘法。 Halide 针对 RTX 2060 进行了调整。在该 GPU 上,我的 Halide 计时为 0.69ms,cublas 计时为 0.51ms。
确保运行时设置了环境变量 HL_CUDA_JIT_MAX_REGISTERS=256。矩阵乘法对可用寄存器的数量非常敏感,以至于为了获得更多寄存器而牺牲占用是值得的。事实上,它对寄存器可用性非常敏感,我认为为了做得更好,我需要直接在 SASS 中编写,或者至少说服 LLVM 在使用这些值来稍微缩小生命范围之前不要重新排序负载。