首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenMP中用于进度报告的增量共享循环计数器

OpenMP中用于进度报告的增量共享循环计数器
EN

Stack Overflow用户
提问于 2015-04-07 00:39:10
回答 2查看 2.7K关注 0票数 4

我想要跟踪通过一个长期运行的射线跟踪过程处理的总像素和射线。如果每次迭代都更新共享变量,由于同步的原因,这个过程会明显减慢。我想要跟踪的进展,仍然得到准确的计数结果在最后。有没有一种方法可以用OpenMP for循环来实现呢?

下面是一些有问题的循环代码:

代码语言:javascript
复制
void Raytracer::trace(RenderTarget& renderTarget, const Scene& scene, std::atomic<int>& sharedPixelCount, std::atomic<int>& sharedRayCount)
{
    int width = renderTarget.getWidth();
    int height = renderTarget.getHeight();
    int totalPixelCount = width * height;

    #pragma omp parallel for schedule(dynamic, 4096)
    for (int i = 0; i < totalPixelCount; ++i)
    {
        int x = i % width;
        int y = i / width;

        Ray rayToScene = scene.camera.getRay(x, y);
        shootRay(rayToScene, scene, sharedRayCount); // will increment sharedRayCount
        renderTarget.setPixel(x, y, rayToScene.color.clamped());

        ++sharedPixelCount;
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-18 17:25:11

下面是一个如何做到这一点的例子:

代码语言:javascript
复制
void Raytracer::trace(RenderTarget& renderTarget, const Scene& scene, std::atomic<int>& sharedPixelCount, std::atomic<int>& sharedRayCount)
{
    int width = renderTarget.getWidth();
    int height = renderTarget.getHeight();
    int totalPixelCount = width * height;
    int rayCount = 0;
    int previousRayCount = 0;

    #pragma omp parallel for schedule(dynamic, 1000) reduction(+:rayCount) firstprivate(previousRayCount)
    for (int i = 0; i < totalPixelCount; ++i)
    {
        int x = i % width;
        int y = i / width;

        Ray rayToScene = scene.camera.getRay(x, y);
        shootRay(rayToScene, scene, rayCount);
        renderTarget.setPixel(x, y, rayToScene.color.clamped());

        if ((i + 1) % 100 == 0)
        {
            sharedPixelCount += 100;
            sharedRayCount += (rayCount - previousRayCount);
            previousRayCount = rayCount;
        }
    }

    sharedPixelCount = totalPixelCount;
    sharedRayCount = rayCount;
}

当循环运行时,它不会100%的精确,但是误差是可以忽略不计的。最后将报告确切的数值。

票数 0
EN

Stack Overflow用户

发布于 2015-04-20 04:54:21

既然您的动态调度并行- for循环的块大小为4096,为什么不使用它作为摊销计数器更新的粒度呢?

例如,下面这样的内容可能会有效。我没有测试这段代码,您可能需要为totalPixelCount%4096!=0添加一些簿记。

与前面的答案不同,这不会向您的循环中添加分支,除了循环本身所隐含的分支之外,许多处理器已经对其进行了优化指令。它也不需要任何额外的变量或算术。

代码语言:javascript
复制
void Raytracer::trace(RenderTarget& renderTarget, const Scene& scene, std::atomic<int>& sharedPixelCount, std::atomic<int>& sharedRayCount)
{
    int width = renderTarget.getWidth();
    int height = renderTarget.getHeight();
    int totalPixelCount = width * height;

    #pragma omp parallel for schedule(dynamic, 1)
    for (int j = 0; j < totalPixelCount; j+=4096)
    {
      for (int i = j; i < (i+4096); ++i)
      {
        int x = i % width;
        int y = i / width;

        Ray rayToScene = scene.camera.getRay(x, y);
        shootRay(rayToScene, scene, sharedRayCount);
        renderTarget.setPixel(x, y, rayToScene.color.clamped());
      }
      sharedPixelCount += 4096;
    }
}

现在还不清楚为什么需要在这个循环中更新sharedPixelCount,因为它没有在循环体中被引用。如果这是正确的,我建议如下。

代码语言:javascript
复制
void Raytracer::trace(RenderTarget& renderTarget, const Scene& scene, std::atomic<int>& sharedPixelCount, std::atomic<int>& sharedRayCount)
{
    int width = renderTarget.getWidth();
    int height = renderTarget.getHeight();
    int totalPixelCount = width * height;

    int reducePixelCount = 0;
    #pragma omp parallel for schedule(dynamic, 4096) \
                         reduction(+:reducePixelCount) \
                         shared(reducePixelCount)
    for (int i = 0; i < totalPixelCount; ++i)
    {
        int x = i % width;
        int y = i / width;

        Ray rayToScene = scene.camera.getRay(x, y);
        shootRay(rayToScene, scene, sharedRayCount);
        renderTarget.setPixel(x, y, rayToScene.color.clamped());

        ++reducePixelCount; /* thread-local operation, not atomic */
    }

    /* The interoperability of C++11 atomics and OpenMP is not defined yet,
     * so this should just be avoided until OpenMP 5 at the earliest. 
     * It is sufficient to reduce over a non-atomic type and 
     * do the assignment here. */
    sharedPixelCount = reducePixelCount;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29481856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档