N 体问题的一个非常常见的问题是使用双循环来计算粒子之间的相互作用。考虑具有 n 个粒子的 N 体问题,循环可以写成
for (i = 0, i < n; i++)
for (j = i+1, j < n; j++)
// calculate interaction
我的问题是如何使用不同的线程并行化这个循环。目标是每个线程“理想地”必须计算相同数量的交互。
我的想法是在不同的间隔上分离外循环,即 i 循环,比如 a_k=a(k),其中 k = 1,2,...,p 其中 p 是我们想要划分的线程数问题成。
所以,循环可以写成
for (k = 1, k < p; k++)
for (i = a(k), i < a(k+1); i++)
for (j = i+1, j < n; j++)
// calculate interaction
其中最外层的循环,即 k 循环,是要并行化的循环。
因为最内层循环j-cycle的交互次数为n-(i+1),所以每个线程计算的交互次数为
\sum_{i=a(k)}^{a(k+1)} n - (i+1)
这意味着人们想找到离散函数 a_k 使得函数
f[a_k] = \sum_{i=a(k)}^{a(k+1)} n - (i+1)
边界条件 a(1)=0 和 a(p)=n 是一个常数函数,因此迫使每个线程上的交互次数相同。
我尝试过使用不同的“启发式”(例如 a_k 多项式、指数、对数),但到目前为止还没有一个给我一个满意的答案。这个问题的直接解决方案对我来说并不明显。
对于小p,这个问题可以放在“最小化麻袋问题”上,基本上每个a_k都是一个变量来最小化函数
f(a_1,a_2,a_3,...) = 总和(|f[a_k] - n/p|^2)
但是您可能会猜到,对于较高的 p 值,这不是有效的(甚至收敛)。
有谁知道如何解决这个问题?