11

我做了一个简单的实验,通过实现简单的字符搜索算法在 CPU 和 GPU 上搜索 1.000.000 行,每行 50 个字符(50 百万字符映射)(使用 iOS8 Metal 计算管道)。

CPU 实现使用简单的循环,Metal 实现给每个内核 1 行来处理(下面的源代码)。

令我惊讶的是,Metal 实现平均比简单的线性 CPU(如果我使用 1 个内核)慢 2-3 倍,如果我使用 2 个内核(每个内核搜索一半数据库)则慢 3-4 倍!我尝试了每组不同的线程(16、32、64、128、512),但仍然得到非常相似的结果。

iPhone 6:

CPU 1 core:  approx 0.12 sec
CPU 2 cores: approx 0.075 sec
GPU: approx 0.35 sec (relEase mode, validation disabled)

我可以看到金属着色器花费了超过 90% 的访问内存(见下文)。

可以做些什么来优化它?

任何见解都将不胜感激,因为互联网上没有很多资源(除了标准的 Apple 编程指南),提供有关 Metal 框架特定的内存访问内部和权衡的详细信息。

金属实现细节:

主机代码要点: https ://gist.github.com/lukaszmargielewski/0a3b16d4661dd7d7e00d

内核(着色器)代码: https ://gist.github.com/lukaszmargielewski/6b64d06d2d106d110126

GPU 帧捕获分析结果:

在此处输入图像描述

4

2 回答 2

3

GPU 着色器也在内存中垂直移动,而 CPU 则在水平方向移动。当您阅读 charTable 时,请考虑在着色器中以锁步方式执行的每个线程实际上或多或少同时接触的地址。如果您的 charTable 矩阵被转置,GPU 可能会运行得更快。

此外,由于此代码以 SIMD 方式执行,每个 GPU 线程可能必须将循环运行到完整的搜索短语长度,而 CPU 将利用早期输出。如果您删除早期输出并保持代码简单,GPU 代码实际上可能会运行得更快一些。很大程度上取决于搜索短语的长度和匹配的可能性。

于 2016-06-18T17:01:04.433 回答
0

我也会猜测一下,gpu 没有针对 if/else 进行优化,它不会预测分支(它可能同时执行),尝试以更线性的方式重写算法,没有任何条件或将它们减少到最低限度.

于 2015-06-03T18:48:45.800 回答