我有一组计算模型,这些模型可以描述为异步蜂窝自动机。这些模型类似于Ising模型,但稍微复杂一些。这样的模型似乎可以从在GPU而非CPU上运行中受益。不幸的是,并行化这样一个模型不是很简单,而且我也不清楚如何去实现它。我知道有关于该主题的文献,但似乎所有这些文献都是针对对算法复杂性细节感兴趣的铁杆计算机科学家,而不是像我这样只想要描述我可以实现的东西的人,以及因此,我觉得它是不可渗透的。
为了清楚起见,我并不是在寻找最佳算法,而是希望可以在CUDA中快速实现的最佳算法比我的CPU实现有明显的提高。在这个项目中,程序员的时间比计算机的时间更多地是一个限制因素。
我还应该澄清,异步蜂窝自动机与同步自动机是完全不同的事情,并且并行化同步CA的技术(例如Conway的生活)不能轻易地适应此问题。区别在于,同步CA在每个时间步同时更新每个小区,而异步CA在每个时间步更新随机选择的本地区域,如下所述。
我希望并行化的模型是在由约100000个单元组成的网格(通常是六角形)上实现的(尽管我想使用更多),用于运行它们的非并行算法如下所示:
随机选择一对相邻的单元格
根据围绕这些单元格的局部邻域计算“能量”函数
以取决于的概率(使用为参数),要么交换两个单元的状态,要么不执行任何操作。
无限重复上述步骤。
边界条件也有一些复杂性,但是我想这些对于并行化不会造成太大困难。
值得一提的是,我对这些系统的瞬态动力学感兴趣,而不仅仅是平衡状态,因此我需要具有与上述等效的动力学特性的东西,而不是仅仅具有相同平衡分布的东西。(因此,chequerboard算法的变化不是我想要的。)
并行化上述算法的主要困难是冲突。由于所有计算仅取决于晶格的局部区域,因此许多晶格位点可以并行更新,只要它们的邻域不重叠即可。问题是如何避免这种重叠。我可以想到几种方法,但是我不知道哪种方法最适合实施。这些如下:
使用CPU生成随机网格站点的列表并检查冲突。当网格站点的数量等于GPU处理器的数量时,或者如果检测到冲突,请将每组坐标发送到GPU单元以更新相应的网格站点。这将很容易实现,但可能不会大大提高速度,因为检查CPU上的冲突可能不会比对CPU进行整个更新便宜得多。
将网格划分为区域(每个GPU单元一个),并拥有一个GPU单元负责随机选择和更新其区域内的网格单元。但是这个想法有很多我不知道如何解决的问题,最明显的是当一个单位选择一个与其区域边缘重叠的邻域时应该发生什么。
大致如下所示:让时间分步进行。将晶格分成不同的根据某个预定义方案在每个时间步上设置一组区域,并让每个GPU单元随机选择和更新一对邻域不与区域边界重叠的网格单元。由于边界每时每刻都在变化,因此只要区域相对较大,此约束就不会对动力学产生太大影响。这似乎易于实现并且可能很快,但是我不知道它对动态的近似程度,或者在每个时间步长上选择区域边界的最佳方案是什么。我发现了一些对“块同步细胞自动机”的引用,它们可能与这个想法相同或不同。(我不知道,因为似乎该方法的所有描述要么都是俄语的,要么是我无法访问的资源。)
我的具体问题如下:
以上任何算法是否是处理异步CA模型的GPU并行化的明智方法?
有没有更好的办法?
是否存在针对此类问题的现有库代码?
在哪里可以找到“块同步”方法的清晰英语描述?
进展
我相信我已经想出了一种可能合适的并行化异步CA的方法。下面概述的算法适用于一次仅更新一个单元的普通异步CA,而不是像我的那样更新相邻的一对单元。将其推广到我的具体情况有一些问题,但是我认为我有一个解决方案的想法。但是,由于下面讨论的原因,我不确定它将带来多少速度优势。
这个想法是用等效的随机同步CA(SCA)代替异步CA(以下称为ACA)。为此,我们首先想到ACA是一个泊松过程。即,时间连续进行,并且每个单元以每单位时间执行其更新功能的恒定概率独立于其他单元。
我们构造了一个SCA,该SCA的每个单元均存储两件事:该单元的状态 (即,在顺序实现中将存储在每个单元中的数据),以及一个浮点数代表(连续)时,在其将在下一次更新。此连续时间不对应于SCA的更新步骤。我将后者称为“逻辑时间”。时间值根据指数分布随机初始化:。(其中是一个可以任意选择其值的参数。)
在每个逻辑时间步,SCA的单元将更新如下:
如果对于附近的任何,时间,则不执行任何操作。
否则,(1)使用与原始ACA相同的规则,根据相邻小区的状态更新状态;(2)生成一个随机值并将更新为。
我相信这保证了将以可以被“解码”的顺序更新单元以对应于原始ACA,同时避免冲突并允许并行更新某些单元。但是,由于上面的第一个要点,这意味着大多数GPU处理器在SCA的每个时间步上都会大部分处于空闲状态,这不理想。
我需要进一步考虑是否可以提高该算法的性能,以及如何扩展该算法以处理ACA中同时更新多个单元的情况。但是,它看起来很有希望,所以我想我将在这里进行描述,以防万一(a)知道文献中类似的内容,或者(b)可以提供对这些剩余问题的任何见解。
exp()
),所以我认为将其分布在多个线程上没有多大意义。我认为最好尝试并行更新多对,每个线程一对,这样对我来说更容易。