gpt4 book ai didi

java - 使用 Aparapi 计算 vector 中的不同值

转载 作者:太空宇宙 更新时间:2023-11-04 12:22:07 25 4
gpt4 key购买 nike

我想与 APARAPI 并行实现一个熵函数。在该函数中,我需要计算 vector 中的不同键,但它无法正确执行。

假设我们只有 3 个不同的值。这是我的代码:

final int[] V = new int[1024];
// Initialization for V values
final int[] count = new int[3];
Kernel kernel = new Kernel(){
@Override
public void run(){
int gid = getGlobalId();
count[V[gid]]++;
}
};
kernel.execute(Range.create(V.length));
kernel.dispose();

运行此代码段后,当我打印 count[] 值时,它给出了 1,1,1。看来 count[V[gid]]++ 对于每个 V[gid] 只执行 1 次。

谢谢。

最佳答案

所以问题就在这里。++ 运算符实际上是三个操作合二为一:读取当前值、递增它、写入新值。在 Aparapi 中,可能有 1024 个 GPU 线程同时运行。这意味着它们将读取该值,可能在值为 0 时始终读取该值,然后将其递增到 1,然后所有 1024 个线程都将写入 1。因此,它的行为符合预期。

您尝试执行的操作称为 Map-reduce 函数。您只是跳过了很多步骤。您需要记住 Aparapi 是一个没有线程安全的系统,因此您必须编写算法来适应这一点。这就是 Map-reduce 发挥作用的地方,这里是如何做到这一点。我刚刚编写了它并将其添加到新家的 Aparapi 存储库中,详细信息如下。

int size = 1024;
final int count = 3;
final int[] V = new int[size];

//lets fill in V randomly...
for (int i = 0; i < size; i++) {
//random number either 0, 1, or 2
V[i] = (int) (Math.random() * 3);
}

//this will hold our values between the phases.
int[][] totals = new int[count][size];

///////////////
// MAP PHASE //
///////////////
final int[][] kernelTotals = totals;
Kernel mapKernel = new Kernel() {
@Override
public void run() {
int gid = getGlobalId();
int value = V[gid];
for(int index = 0; index < count; index++) {
if (value == index)
kernelTotals[index][gid] = 1;
}
}
};
mapKernel.execute(Range.create(size));
mapKernel.dispose();
totals = kernelTotals;

//////////////////
// REDUCE PHASE //
//////////////////
while (size > 1) {
int nextSize = size / 2;
final int[][] currentTotals = totals;
final int[][] nextTotals = new int[count][nextSize];
Kernel reduceKernel = new Kernel() {
@Override
public void run() {
int gid = getGlobalId();
for(int index = 0; index < count; index++) {
nextTotals[index][gid] = currentTotals[index][gid * 2] + currentTotals[index][gid * 2 + 1];
}
}
};
reduceKernel.execute(Range.create(nextSize));
reduceKernel.dispose();

totals = nextTotals;
size = nextSize;
}
assert size == 1;

/////////////////////////////
// Done, just print it out //
/////////////////////////////
int[] results = new int[3];
results[0] = totals[0][0];
results[1] = totals[1][0];
results[2] = totals[2][0];

System.out.println(Arrays.toString(results));

请记住,虽然它看起来效率低下,但实际上在更大的数量上效果很好。这个算法工作得很好

size = 1048576.

使用新的大小,我的系统在大约一秒内计算出以下结果。

[349602, 349698, 349276]

最后一点,您可能需要考虑转向更活跃的项目 aparapi.com 。它包括对错误的多项修复以及与上面链接的旧库相比的许多额外功能和性能增强。它也在 Maven 中心,有大约十几个版本。所以使用起来更方便。我刚刚在这个答案中编写了代码,但决定在新的 Aparapi 存储库的示例部分中使用它,您可以在 the following link in the new Aparapi repository 找到它。 .

关于java - 使用 Aparapi 计算 vector 中的不同值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38762986/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com