假设我有一些算法generateRandomNumbersAndTestThem(),它以概率p和false返回true,概率为1-p。通常p非常小,例如P = 0.000001
我正在尝试在JOCL中构建一个程序,估计p如下:generateRandomNumbersAndTestThem()在所有可用的着色器核心(最好是多个GPU)上并行执行,直到找到至少100个trues。然后p的估计值为100 / n,其中n是执行generateRandomNumbersAndTestThem()的总次数。
对于p = 0.0000001,这意味着大约10 ^ 9次独立尝试,这应该说明我为什么要在GPU上执行此操作。但我正在努力解决如何正确实施停止条件。我的想法是将这些内容作为内核:
__kernel void sampleKernel(all_the_input, __global unsigned long *totAttempts) {
int gid = get_global_id(0);
//here code that localizes all_the_input for faster access
while (lessThan100truesFound) {
totAttempts[gid]++;
if (generateRandomNumbersAndTestThem())
reportTrue();
}
}
如果没有严重的性能损失,我该如何实现呢?鉴于
我认为可以像Java的“synchronized”修饰符那样完成某些操作,但我找不到确切的方法。这样做的“正确”方法是什么,即任何方式都可以在没有严重性能损失的情况下工作?
答案 0 :(得分:1)
我建议不要使用全局标志来停止内核,而是运行内核来执行一定数量的尝试,如果已经积累了足够的“成功”,请检查主机,并在必要时重复。在内核中使用未定义长度的循环是不好的,因为GPU驱动程序可能被看门狗计时器杀死。此外,在每次迭代时检查一些全局变量肯定会破坏内核性能。
这样,reportTrue
可以作为atomic_inc
实现到驻留在全局内存中的某个计数器。
__kernel void sampleKernel(all_the_input, __global unsigned long *successes) {
int gid = get_global_id(0);
//here code that localizes all_the_input for faster access
for (int i = 0; i < ATT_PER_THREAD; ++i) {
if (generateRandomNumbersAndTestThem())
atomic_inc(successes);
}
}
ATT_PER_THREAD将根据执行generateRandomNumbersAndTestThem()
所需的时间进行调整。内核启动开销非常小,因此通常不需要使内核运行超过0.1-1秒