【问题标题】:filtering an image, best practices过滤图像,最佳实践
【发布时间】:2014-05-23 00:47:28
【问题描述】:

我有一个输入图像“让它成为一个 1024 * 1024 像素的缓冲区,带有 RGBA 颜色数据”

我想要为每个像素做的是根据邻居过滤它,例如 x 和 y 方向的 [-15,15]

所以我担心的是,使用全局内存执行此操作将对每个像素进行 31 * 31 次全局内存访问“这将是非常性能瓶颈”,而且我不确定多个线程尝试读取的行为在同一时间相同的内存位置“可能是其中一些无法读取所以 -> 垃圾数据输入 -> 垃圾数据输出”

这个问题是针对 CUDA 或 OpenCL 的,因为概念应该是相同的 我知道共享内存(每个工作组)或本地内存(每个线程)无法解决这个问题,因为我无法读取另一个线程本地内存或另一个组共享内存“如果我误解了这个概念,请纠正我”

【问题讨论】:

    标签: cuda opencl gpgpu


    【解决方案1】:

    共享内存是解决此问题的典型方法,尽管模板区域 (31*31) 相当大。然而,仍然可以获得数据重用的好处。由于相邻像素计算仅扩展一列所需的区域,因此在 32 位 RGBA 像素的 16KB 共享内存阵列中,您可以拥有足够的数据供至少 64 个线程在单个共享内存负载中协同计算它们的像素值。

    关于多线程读取同一位置的问题,不存在垃圾数据读取的可能性。当然,争用可能会导致性能影响,但事实上,随着内核中有序的 for 循环进程,无论如何都不会有线程同时读取相同的位置。通过适当的数据组织,将有很好的机会从全局内存中合并读取,并且共享内存中不会发生存储库冲突。

    这类问题非常适合 GPU,例如CUDA 或 OpenCL,SO 上有很多这样的程序示例。

    【讨论】:

    • 让组线程排列成[0~31] [0~31] ...第一组线程20如何访问第二组线程20的共享内存?因为窗口围绕每个线程“所以我必须访问之前的 15 个线程和之后的 15 个线程”
    • 共享内存与单个线程或线程组无关。它与一个线程块相关联,即一个线程块中的所有线程。线程块中的任何线程都可以访问与该线程块关联的共享内存。
    • 这个我知道!!,块内的所有32*32线程都可以访问这个块中的共享内存,但是这里的问题例如:全局内存IDpixel(420,390)要访问从 (420-15,390-15) 到 (420+15,390+15) 范围内的像素,所以如果我们将全局内存存储到共享内存中,只有块中的中心线程会准备好数据,所有其他线程都需要访问邻居块共享内存“这是不可能的”
    • 是的,所以您不只是将 32*32 数据元素加载到共享内存中。您为每个附加线程加载 32*32 个数据元素和一个附加列(32 个元素)。该附加线程所需的其余数据与您为前一个线程加载的数据相同。而且我并不是建议使用 32*32 线程块。我建议总共有 64 个线程。对于 64 个线程,共享内存中大约需要 32*32 像素,再加上 32*63 像素。这当然是可行的,并且将为所有 64 个线程提供足够的数据来计算 64 个相邻像素的值
    • 这是fully worked example code。它恰好是 3D 而不是 2D,但概念是相同的。
    猜你喜欢
    • 2015-11-16
    • 2013-02-04
    • 1970-01-01
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 2010-10-18
    相关资源
    最近更新 更多