我有一种情况,我使用openMP作为Xeon Phi协处理器,我有机会并行化“令人尴尬的并行”双循环。
然而,for循环遍历上三角形(包括对角线):
for (int i = 0; i < n; i++)
// access some arrays with the value of i
for (int j = i; j < n; j++)
// do some stuff with the values of j and i
所以,我已经得到了循环的总大小,
for (int q = 0; q < ((n*n - n)/2)+n; q++)
// Do stuff
但我在努力的地方是:
如何从 q 计算 i 和 j ?可能吗?
与此同时,我只是在做完整的矩阵,从那里计算i和j,只在j> = i时才做我的东西...但是这仍然留下了大量的线程开销。
答案 0 :(得分:1)
如果我重述您的问题,要从i
查找j
和q
,您需要最大的i
q >= i*n - (i-1)*i/2
将j
定义为
j = i + (q - i*n - (i-1)*i/2)
如果你有这么大的i
,那么
(i+1)*n - i*(i+1)/2 > q >= i*n - (i-1)*i/2
n-i > (q - i*n - (i-1)*i/2) >= 0
n > j = i + (q - i*n - (i-1)*i/2) >= i
这是找到i的第一个迭代方法:
for (i = 0; q >= i*n - (i-1)*i/2; ++i);
i = i-1;
如果迭代q
,i
的计算很可能会利用迭代过程。
第二种方法可以使用sqrt,因为
i*n - i²/2 + i/2 ~ q
i²/2 - i(n+1/2) + q ~ 0
delta = (n+0.5)² - 2q
i ~ (n+0.5) - sqrt(delta)
i
可以定义为floor((n+0.5) - sqrt((n+0.5)² - 2q))
答案 1 :(得分:0)
好的,就我所知,这不是一个答案。但是,这是一种解决方法(目前)。
我正在考虑它,创建一个数组(或相应的指针),a[(n*n + n)/2 + n][2]
,并在我的调用代码中读取相应的i
和j
值,然后传递给它我的功能将允许加速。
答案 2 :(得分:0)
你可以让你的循环迭代,因为它在整个矩阵上迭代 只是为了跟踪当前行,每次输入新行时,都会使用该行的值增加索引。
然后:i == line
和j == i%n
。
请参阅此代码:
int main() {
int n = 10;
int line = 0;
for (int i=0; i<n*n; i++){
if (i%n == 0 && i!=0){
line++;
i += line;
cout << endl;
}
cout << "("<<line<<","<<i%n<<")";
}
return 0;
}