Taichi GPU 内核如何用 ti.sync() 正确测量执行时间?
Taichi GPU 内核如何用 ti.sync() 正确测量执行时间【免费下载链接】taichiProductive, portable, and performant GPU programming in Python.项目地址: https://gitcode.com/GitHub_Trending/ta/taichi在 Taichi 中给 GPU 内核计时是一个容易踩坑的操作使用 GPU 后端时内核被编译后是发送到 GPU 队列执行的Python 程序不会等待内核执行完就继续执行下一条语句。如果你直接在内核调用前后用time.time()掐表测出来的时间并不包含内核在 GPU 上的实际执行时间。本文基于 kernel_sync 文档说明如何在内核调用后显式调用ti.sync()等待内核完成从而得到正确的执行时间。适用前提程序运行在 GPU 后端ti.init(archti.gpu)内核本身没有返回值、不访问 field、也没有print等需要同步数据的操作。为什么直接计时会漏掉 GPU 执行时间下面的代码来自官方文档定义了一个计算量很大的benchmark内核并尝试测量其耗时import time import taichi as ti ti.init(archti.gpu) ti.kernel def benchmark(): x 1.0 for i in range(1000): for j in range(10000): x ti.sin(float(i j)) start time.time() benchmark() end time.time() print(end - start)文档指出虽然benchmark是一个计算密集的内核但程序不会等待它执行完才执行后续语句benchmark的执行时间被排除在计时之外。也就是说这里打印出来的end - start只覆盖了内核编译与提交到 GPU 队列的开销远小于 GPU 上真正的计算时间。在内核调用后加 ti.sync() 再计时修正方法是在内核调用之后、读取结束时间之前显式调用ti.sync()import time import taichi as ti ti.init(archti.gpu) ti.kernel def benchmark(): x 1.0 for i in range(10000): for j in range(100000): x ti.sin(float(i j)) start time.time() benchmark() ti.sync() end time.time() print(end - start)ti.sync()会阻塞程序等待 GPU 队列中排在前面的所有内核任务执行完毕后才继续执行后续语句因此end - start此时包含了内核在 GPU 上的执行时间。FAQ 中也提到ti.sync()的作用类似 CUDA 的cudaStreamSynchronize()。验证方式同样是行为层面的对比两段代码第一段无ti.sync()的计时结果不包含内核执行时间第二段在benchmark()与end time.time()之间加入ti.sync()后计时结果才会反映 GPU 上的实际执行耗时。文档没有给出固定的预期数值实际输出取决于你的硬件。哪些情况下不需要手动 ti.sync()大多数时候 Taichi 会自动处理数据同步以下情形无需手动调用ti.sync()内核有返回值Taichi 会等待内核完成后才把返回值交还给 Python 作用域在 Python 作用域调用x.to_numpy()如果 fieldx正被其他内核使用Taichi 会确保使用该 field 的内核先完成在 Python 作用域访问或修改 Taichi field同样会先确保使用 field 的内核结束。文档示例之所以必须显式调用ti.sync()正是因为这个内核没有返回值、不含 print 语句、也不涉及任何 field 操作属于典型的发射后不管内核。另外注意 CPU 后端的差异在 CPU 后端上所有内核调用都是阻塞的程序会等待当前内核结束再执行下一条语句因此CPU 后端既不用担心数据依赖也不需要调用ti.sync()。ti.sync()的计时修正只针对 GPU 后端。可选用 KernelProfiler 获取内核级性能数据如果目标不止是测一次耗时而是想看每个内核的统计信息可以在ti.init()时启用kernel_profilerTrue再用ti.profiler.print_kernel_profiler_info()输出结果支持 count 与 trace 两种模式。Profiler 文档 特别强调了两点KernelProfiler目前仅支持 CPU 和 CUDA 后端程序运行在 GPU 上时执行性能分析前要先调用ti.sync()与本文的计时要求一致。文档还建议在多次运行性能分析后观察最小或平均执行时间而不是只看单次结果。【免费下载链接】taichiProductive, portable, and performant GPU programming in Python.项目地址: https://gitcode.com/GitHub_Trending/ta/taichi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考