我有一个在开放 CL 中运行的内核(通过 jocl 前端),与其他内核相比,它的运行速度非常慢,我试图弄清楚为什么以及如何加速它。这个内核非常基础。它的唯一工作是抽取我们拥有的样本点的数量。它将输入数组中的每个第 N 个点复制到一个较小的输出数组以缩小我们的数组大小。
内核被传递一个浮点数,指定在“好”点之间跳过多少点。因此,如果超过 1.5 分,它将跳过 1 分,10 分 2 分,然后 1 分等,以保持平均每 1.5 分被跳过。输入数组已经在 GPU 上(它是由较早的内核生成的),而输出数组将保留在内核上,因此无需向 CPU 传输数据或从 CPU 传输数据。
这个内核的运行速度比其他任何内核慢 3-5 倍;并且比一些快速内核慢 20 倍。我意识到我因为没有合并我的数组访问而受到惩罚;但我不敢相信它会导致我跑得这么慢。在所有其他内核都接触阵列中的每个样本之后,我认为接触阵列中的每个 X 样本,即使没有合并,至少应该与接触阵列中的每个样本的速度大致相同。
原始内核实际上一次抽取了两个数组,用于实数和虚数数据。我尝试将内核拆分为两个内核调用,一个用于抽取实数,一个用于抽取虚数据;但这根本没有帮助。同样,我尝试通过让一个线程负责抽取 3-4 个点来“展开”内核;但这没有任何帮助。我尝试弄乱传递给每个内核调用的数据大小(即一个内核调用数千个数据点,或者几个内核调用少量数据点),这使我能够调整小的性能提升;但没有达到我认为值得在 GPU 上实现该内核所需的数量级。
只是为了给人一种规模感,这个内核每次迭代运行需要 98 毫秒,而对于相同的输入数组大小,FFT 只需要 32 毫秒,而其他每个内核都需要 5 毫秒或更短的时间。与其他正在运行的内核相比,还有什么可能导致如此简单的内核运行得如此缓慢?是否有可能我实际上无法充分优化此内核以保证在 GPU 上运行它。我不需要这个内核比 CPU 运行得更快;与 CPU 相比没有那么慢,所以我可以将所有处理都保留在 GPU 上。