gpt4 book ai didi

cuda - 3D 纹理内存是如何缓存的?

转载 作者:行者123 更新时间:2023-12-04 15:20:03 27 4
gpt4 key购买 nike

我有一个应用程序,其中 96% 的时间都花在 3D 纹理内存插值读取上(图中的红点)。

我的内核设计为在任意穿过纹理内存的线上进行 1000~ 次内存读取,每行一个线程(蓝线)。这条线非常密集,彼此非常靠近,以几乎平行的方向行进。

该图像显示了我正在谈论的概念。想象一下图像是来自 3D 纹理内存的单个“切片”,例如z=24 .图像重复所有 z .
enter image description here

目前,我正在一行接一行地执行线程,但我意识到如果我在同一块中调用相邻的行,我可能能够从纹理内存局部性中受益,从而减少内存读取的时间。

我的问题是

  • 如果我有带线性插值的 3D 纹理,我怎样才能从数据局部性中获益最多?通过在 2D 中的同一块中运行相邻线或在 3D 中运行相邻线(3D 相邻线或每个切片仅相邻线)?
  • 缓存有多大(或者我如何在规范中检查它)?它是否加载例如被问到的体素和 +-50 在它周围的各个方向?这将与我在每个块中放置的相邻线的数量直接相关!
  • 插值如何应用于纹理内存缓存?插值是否也在缓存中执行,或者它的插值会减少内存延迟,因为它需要在文本内存本身中完成?


  • 如果有帮助,可以使用 NVIDIA TESLA K40、CUDA 7.5。

    最佳答案

    由于这个问题越来越老,而且我提出的一些问题似乎没有答案,我将根据我构建 TIGRE 工具箱的研究给出一个基准答案。您可以在 Github repo 中获取源代码.

    由于答案基于工具箱的特定应用程序,即计算机断层扫描,这意味着我的结果不一定适用于所有使用纹理内存的应用程序。此外,我的 GPU(见上文)相当不错,因此您的里程可能因不同的硬件而异。

    具体情况

    需要注意的是:这是一个锥形束计算机断层扫描应用程序。这意味着:

  • 线条或多或少沿图像均匀分布,覆盖大部分
  • 这些线或多或少与相邻线平行,并且主要总是在一个平面内。例如。它们总是或多或少是水平的,而不是垂直的。
  • 线条顶部的采样率是相同的,这意味着相邻线条将始终对彼此非常接近的下一个点进行采样。

  • 所有这些信息对于内存局部性都很重要。

    此外,正如问题中所说,内核 96% 的时间是内存读取,因此可以安全地假设报告的内核时间的变化是由于内存读取速度的变化。

    问题

    If I have 3D texture with linear interpolation, how could I benefit most from the data locality? By running adjacent lines in the same block in 2D or adjacent lines in 3D (3D neighbors or just neighbors per slice)?



    一旦对纹理内存有更多的经验,就会发现直接的答案是:将尽可能多的相邻行一起运行。内存读取在图像索引中越接近越好。

    这对断层扫描有效意味着运行方形探测器像素块。将光线(原始图像中的蓝线)打包在一起。

    How "big" is the cache (or how can I check this in the specs)? Does it load e.g. the asked voxel and +-50 around it in every direction? This will directly relate with the amount of neighboring lines I'd put in each block!



    虽然不可能说,但凭经验我发现运行较小的块更好。我的结果表明,对于 512^3 的图像,具有 512^2 条光线,采样率为 ~2 个样本/体素,块大小:
    32x32 -> [18~25] ms
    16x16 -> [14~18] ms
    8x8 -> [11~14] ms
    4x4 -> [25~29] ms

    块大小实际上是一起计算的正方形相邻光线的大小。例如。 32x32 意味着将并行计算 1024 个 X 射线,并在一个 32x32 正方形块中彼此相邻。由于在每一行中执行完全相同的操作,这意味着样本是在图像上的 32x32 平面上获取的,覆盖大约 32x32x1 索引。

    可以预见,在某些时候,当减小块的大小时,速度会再次变慢,但这是(至少对我而言)令人惊讶的低值。我认为这暗示内存缓存从图像加载相对较小的数据块。

    此结果显示了原始问题中未询问的附加信息: 关于速度越界样本会发生什么 .添加任何 if内核的条件会显着减慢它的速度,我对内核进行编程的方式是在确保不在图像的线上的一个点上开始采样,并在类似情况下停止。这是通过在图像周围创建一个虚构的“球体”来完成的,并且始终采样相同的数量,而与图像和线条本身之间的角度无关。

    如果你看到我展示的每个内核的时间,你会注意到所有这些都是 [t ~sqrt(2)*t] ,我已经检查过确实更长的时间是从线条和图像之间的角度是 45 度的倍数开始,更多的样本落在图像(纹理)内。

    这意味着对图像索引 ( tex3d(tex, -5,-5,-5) ) 的采样是 计算免费 .没有时间花在越界阅读上。读取大量越界点比检查点是否落在图像内更好,如 if条件会减慢内核,而越界采样的成本为零。

    How does the interpolation applies to texture memory cache? Is the interpolation also performed in the cache, or the fact that its interpolated will reduce the memory latency because it needs to be done in the text memory itself?



    为了测试这一点,我运行了相同的代码,但使用了线性插值( cudaFilterModeLinear )和最近邻插值( cudaFilterModePoint )。正如预期的那样,当添加最近邻插值时,速度会有所提高。对于 8x8在我的电脑中具有前面提到的图像大小的块:
    Linear  ->  [11~14] ms
    Nearest -> [ 9~10] ms

    加速不是很大,但很重要。正如预期的那样,这暗示缓存插入数据所花费的时间是可测量的,因此在设计应用程序时需要注意这一点。

    关于cuda - 3D 纹理内存是如何缓存的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35937598/

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