假设以下假设任务:
我给了一个整数A(比方说,32位双)和一个大整数B的数组(相同的类型)。整数数组的大小在运行时是固定的(不会在运行中增长)但是具有任意大小,除非它总是适合RAM或VRAM(以最小者为准)。为了这种情况,整数数组可以位于RAM和VRAM中;忽略在启动时传输此初始数据集的任何时间成本。
任务是将A与每个B进行比较,并且仅当测试对于所有B的测试为真时才返回true,否则返回false。为了这个场景,让比大于比较(尽管如果你的答案对于稍微复杂的比较有所不同,我会感兴趣)。
一个天真的并行实现可能涉及切割集合B并将比较工作负载分布在多个核心上。核心的工作负载将完全独立,除非失败的比较会中断所有其他工作负载,因为结果将立即为假。中断在此实现中发挥作用;虽然我想象随着整数数组的增大,概率会不断下降。
我的问题有三个:
这种情况是否适合在GPU上进行并行处理。如果是这样,在什么情况下呢?或者这是一个误导性的情况,直接CPU实现实际上是最快的?
你能否建议一个改进的并行算法超过天真的算法?
答案 0 :(得分:1)
如果我正确地理解了您的问题,那么您要执行的是还原操作。有问题的操作相当于MATLAB / Numpy all(A[:] == B)
。要回答这三个部分:
答案 1 :(得分:1)
忽略传输此初始数据集的任何时间成本 启动
如果在数百万或数十亿元素中只有少数flase条件,你可以尝试一个opencl示例:
// A=5 and B=arr
int id=get_global_id(0);
if(arr[id]!=5)
{
atomic_add(arr,1);
}
和它一样快。如果所有条件都是" true"
,则arr [0]必须为零如果你不确定只有少数几个或数百万个(这会使原子功能变慢),你可以进行单程预处理以减少错误次数:
int id=get_global_id(0);
// get arr[id*128] to arr[id*128+128] into local/private mem
// check if a single false exists.
// if yes, set all cells true condition except one
// write results back to a temporary arr2 to be used
这会将整个数组复制到另一个数组,但如果您可以忽略从主机设备传输的时间增量,则也应该忽略它。除此之外,只有两个内核不应该花费超过1毫秒的开销(不包括内存读写)
如果数据适合缓存,则第二个内核(具有原子功能的内核)将访问它而不是全局内存。
如果转移时间开始,如果线程可以从整个阵列中分离,则可以使用流水线上传计算下载操作隐藏其延迟。
答案 2 :(得分:1)
我认为在这种情况下,您可以从使用GPU中获得最小的好处。我也认为这种情况下,任何形式的并行都很难获得良好的回报。
关于内存速度与CPU的评论
为什么我相信这个?看哪:性能差距(可疑的单位)。
这里的重点是CPU已经非常快。并且,随着SIMD成为一种东西,它们将变得更快。
与此同时,内存变得越来越慢。图表中未显示的是存储器总线,它将数据传送到CPU或从CPU传送数据。这些也越来越快,但速度很慢。
由于RAM和硬盘速度很慢,CPU会尝试将数据存储在称为L1,L2和L3缓存的“小RAM”中。这些缓存超快,但超小。但是,如果您可以设计一个算法重复使用相同的内存,这些缓存可以加快一个数量级的速度。例如,this site讨论了优化矩阵乘法以进行缓存重用。加速是戏剧性的:
对于350x350矩阵的所有内容,天真实现(3Loop)的速度急剧下降。为什么是这样?因为正在使用双精度数字(每个8字节),所以这是测试机器上的1MB L2缓存被填充的点。您在其他实现中看到的所有速度增益都来自策略性地重用内存,因此此缓存不会快速清空。
在您的算法中缓存
根据定义,您的算法不会重用内存。实际上,它具有最低的内存重用率。这意味着您无法从L1,L2和L3缓存中获益。就好像你已经将CPU直接插入RAM中一样。
如何从RAM获取数据?
这是CPU的简化图:
请注意,每个核心都有自己的专用L1缓存。核心对共享L2缓存。 RAM由每个人共享,并通过总线访问。
这意味着如果两个内核想要同时从RAM获取内容,那么其中只有一个内核将会成功。另一个将坐在那里做 nothing 。你试图从RAM中获取内容的核心越多,这就越糟糕。
对于大多数代码来说,问题不是太糟糕,因为RAM很少被访问。但是,对于您的代码,我之前谈到的性能差距,加上您的算法的不可缓存设计,意味着您的代码的大部分时间花在从RAM获取内容上。这意味着内核几乎总是相互冲突,因为内存带宽有限。
使用GPU怎么样?
GPU并没有真正解决问题:大部分时间仍然用于从RAM中提取内容。除了没有一个慢速总线(从CPU到RAM),你有两个(另一个是从CPU到GPU的总线)。
是否加速取决于CPU,GPU-CPU总线和GPU的相对速度。不过,我怀疑你不会加快速度。 GPU适用于SIMD类型的操作,或maps。您描述的操作是减少或fold:本质上非并行操作。由于映射函数(相等)非常简单,因此GPU将大部分时间用于还原操作。
<强> TL;博士强>
这是memory-bound操作:更多核心和GPU无法解决此问题。