这种循环很难使用SIMD指令进行优化。在大多数SIMD指令集中,不仅没有一种简单的方法来进行这种索引读取(“聚集”)或写入(“分散”),即使存在,这个特定的循环仍然存在您可能遇到的问题两个值在一个SIMD寄存器中映射到相同的id
,例如当
id[0] == 0
id[1] == 1
id[2] == 2
id[3] == 0
在这种情况下
,明显的方法(这里的伪代码)
x = gather(size, id[i]);
y = gather(sum, id[i]);
x += 1; // componentwise
y += value[i];
scatter(x, size, id[i]);
scatter(y, sum, id[i]);
不会工作!
你可以通过,如果有一个非常小的一些可能的情况下(例如,假设sum
和size
只有各3片)通过只是在做蛮力相比,但并没有真正规模。不使用SIMD稍快得到这个
一种方式是通过破坏指令之间的依赖关系使用展开了一下:
int size[10] = { 0 }, size2[10] = { 0 };
int sum[10] = { 0 }, sum2[10] = { 0 };
for (int i = 0; i < N/2; i++) {
int id0 = id[i*2+0], id1 = id[i*2+1];
++size[id0];
++size2[id1];
sum[id0] += value[i*2+0];
sum2[id1] += value[i*2+1];
}
// if N was odd, process last element
if (N & 1) {
++size[id[N]];
sum[id[N]] += value[N];
}
// add partial sums together
for (int i = 0; i < 10; i++) {
size[i] += size2[i];
sum[i] += sum2[i];
}
这是否有助于与否虽然取决于目标CPU上。
只是为了确保,在重新al代码是`size`和`sum`自动变量在这里?如果它们不是(例如,如果它们是通过指针或引用传入到实际例程中的话),那么可能会由于sum和value之间出现混叠的可能性而导致人为的低效率和/大小`和`id`。 – 2010-12-04 20:28:01
这里将并行化算作一个优化吗?即将数组分割成多个子数组,然后将每个子数组传递给一个单独的线程进行迭代,然后在最后组合结果。对于足够大的阵列,至少在多核机器上可以提供很好的加速。 – 2010-12-04 20:32:02
是的,大小和总和是这样的变量。分区听起来像是一个好主意,我会尝试memcpy将它们分解成四个宿区并且并行运行它们。 – Dmi 2010-12-04 20:35:10