For loop OpenCL for loop做奇怪的事情

For loop OpenCL for loop做奇怪的事情,for-loop,opencl,noise,For Loop,Opencl,Noise,我目前正在OpenCL中使用分层八度噪声实现地形生成,我偶然发现了这个问题: float multinoise2d(float2 position, float scale, int octaves, float persistence) { float result = 0.0f; float sample = 0.0f; float coefficient = 1.0f; for(int i = 0; i < octaves; i++){

我目前正在OpenCL中使用分层八度噪声实现地形生成,我偶然发现了这个问题:

float multinoise2d(float2 position, float scale, int octaves, float persistence)
{
    float result = 0.0f;
    float sample = 0.0f;
    float coefficient = 1.0f;

    for(int i = 0; i < octaves; i++){
        // get a sample of a simple signed perlin noise
        sample = sgnoise2d(position/scale);

        if(i > 0){
            // Here is the problem:

            // Implementation A, this works correctly.
            coefficient = pown(persistence, i);

            // Implementation B, using this only the first
            // noise octave is visible in the terrain.
            coefficient = persistence;
            persistence = persistence*persistence;
        }

        result += coefficient * sample;
        scale /= 2.0f;
    }
    return result;
}
float multinoise2d(float2位置、float刻度、int倍频程、float持久性)
{
浮动结果=0.0f;
浮样=0.0f;
浮动系数=1.0f;
对于(int i=0;i<八度;i++){
//获取一个简单的有符号柏林噪声样本
样本=sgnoise2d(位置/刻度);
如果(i>0){
//问题是:
//实现A,这是正确的。
系数=功率(持久性,i);
//实现B,仅使用第一个
//噪声倍频程在地形中可见。
系数=持久性;
持久性=持久性*持久性;
}
结果+=系数*样本;
比例/=2.0f;
}
返回结果;
}
OpenCL是否对循环进行并行化,从而导致这里的同步问题,还是我遗漏了其他东西


感谢您的帮助

我假设这是在CL内核中调用的某种实用方法。Vivek在上面的评论中是正确的:OpenCL不会为您并行化代码。您必须利用OpenCL的功能将问题划分为数据并行块


另外,我在上面的代码中没有看到潜在的同步问题。所有变量都在工作项私有内存空间中。

我假设这是在CL内核中调用的某种实用方法。Vivek在上面的评论中是正确的:OpenCL不会为您并行化代码。您必须利用OpenCL的功能将问题划分为数据并行块


另外,我在上面的代码中没有看到潜在的同步问题。所有变量都在工作项专用内存空间中。

代码的问题在于行

coefficient = persistence;
persistence = persistence*persistence;
应该改成

coefficient = coefficient *persistence;
否则在每次迭代中

第一个系数仅通过持久性增长

pow(persistence, 1) ; pow(persistence, 2); pow(persistence, 3) ....
然而,第二个实现是

pow(persistence, 1); pow(persistence, 2); pow(persistence, 4); pow(persistence, 8) ......
很快,“持久性”将超过float的限制,您的答案将为零(或未定义的行为)

编辑 还有两件事

  • 累加(实现2)不是一个好主意,特别是对于实数和需要精确性的算法。每次累积“持久性”时,您可能会丢失一小部分信息(例如,由于舍入)。尽可能地选择直接计算(第一次实施)而不是累积。(另外,如果这是串行的,那么第二个实现将很容易并行化。)
  • 如果您使用AMD OpenCL,请注意pow()函数。我曾多次在多台机器上遇到这些问题。这些函数有时似乎无缘无故地挂起。仅供参考

  • 代码的问题在于行

    coefficient = persistence;
    persistence = persistence*persistence;
    
    应该改成

    coefficient = coefficient *persistence;
    
    否则在每次迭代中

    第一个系数仅通过持久性增长

    pow(persistence, 1) ; pow(persistence, 2); pow(persistence, 3) ....
    
    然而,第二个实现是

    pow(persistence, 1); pow(persistence, 2); pow(persistence, 4); pow(persistence, 8) ......
    
    很快,“持久性”将超过float的限制,您的答案将为零(或未定义的行为)

    编辑 还有两件事

  • 累加(实现2)不是一个好主意,特别是对于实数和需要精确性的算法。每次累积“持久性”时,您可能会丢失一小部分信息(例如,由于舍入)。尽可能地选择直接计算(第一次实施)而不是累积。(另外,如果这是串行的,那么第二个实现将很容易并行化。)
  • 如果您使用AMD OpenCL,请注意pow()函数。我曾多次在多台机器上遇到这些问题。这些函数有时似乎无缘无故地挂起。仅供参考

  • 使用openCL的代码在哪里?openCL不会对循环进行并行化。您需要使用线程/块编写代码。@Vivek G:某些OpenCL编译器可以自动向量化循环。@Anselm:您认为将pown拆分为两个单独的语句可能会导致同步危险吗?但pown不是一个原子函数;它也可能有同步问题。但正如James在下面所说的,您的内存是所有工作项私有的,所以这是一个没有实际意义的问题?openCL不会对循环进行并行化。您需要使用线程/块编写代码。@Vivek G:某些OpenCL编译器可以自动向量化循环。@Anselm:您认为将pown拆分为两个单独的语句可能会导致同步危险吗?但pown不是一个原子函数;它也可能有同步问题。但正如James在下面所说,您的内存都是工作项私有的,因此这是一个没有意义的问题。好吧,那么一切都很好,因为我不想并行化代码的这一部分(而且不能,因为持久性反馈)。你知道为什么迭代能力不起作用,但是pown起作用了吗?好吧,那么一切都很好,因为我不想并行化那部分代码(而且不能,因为持久性反馈)。你知道为什么迭代能力不起作用,但pown起作用了吗?基础数学再一次失败了。也谢谢你的提示!基础数学又一次失败了。也谢谢你的提示!