【问题标题】:how exactly does CUDA handle a memory access?CUDA 究竟如何处理内存访问?
【发布时间】:2017-01-15 15:35:22
【问题描述】:

我想知道 CUDA 硬件/运行时系统如何处理以下情况。

如果一个warp(以下为warp1)指令涉及访问全局内存(加载/存储);运行时系统安排下一个准备好的扭曲执行。

当新的warp被执行时,

  1. warp1 的“内存访问”是否会并行进行,即在新的 warp 运行时?

  2. 运行时系统会将warp1放入内存访问等待队列吗?一旦内存请求完成,warp 会被移到可运行队列中吗?

  3. 与warp1执行相关的指令指针是否会自动递增并与新的warp执行并行,以注释内存请求已完成?

例如,考虑这个伪代码output=input+array[i];,其中outputinput 都是映射到寄存器的标量变量,而array 保存在全局内存中。

要运行上述指令,我们需要在更新输出之前将array[i] 的值加载到(临时)寄存器中;即上面的指令可以翻译成2条宏汇编指令load reg,reg=&array[i],output_register=input_register+reg

我想知道硬件和运行时系统如何处理上述2条宏汇编指令的执行,因为加载不能立即返回

【问题讨论】:

    标签: cuda gpgpu


    【解决方案1】:

    我不确定我是否正确理解了您的问题,所以我会在阅读时尝试回答:

    1. 是的,当内存事务正在进行时,将继续发出进一步的独立指令。但是,不一定要切换到不同的经线——虽然来自其他经线的指令总是独立的,但来自同一经线的以下指令也可能是独立的,并且同一经线可能会继续运行(即,可能会发出进一步的指令相同的经线)。

    2. 没有。如 1. 中所述,warp 可以并且将继续执行指令,直到相关指令需要加载结果,或者内存栅栏/屏障指令要求它等待存储对其他线程可见的效果。 这可以进一步发布(独立的)加载或存储指令,以便多个内存事务可以同时针对同一个扭曲进行。因此,在发出加载/存储后,warp 的状态不会发生根本性变化,并且在必要时才会停止。

    3. 指令指针将始终自动递增(您从未手动执行此操作,也没有指令允许这样做)。然而,正如 2. 所暗示的,这并不一定表明内存访问已经执行 - 有单独的硬件来跟踪内存访问的进度。

    请注意,Nvidia 完全没有记录硬件实现。如果您搜索 Nvidia 的专利申请,您可能会发现一些可能实现的迹象。

    直到 Fermi 一代(计算能力 2.x)的 GPU 完全在硬件中跟踪未完成的内存事务。虽然 Nvidia 没有记录,但在飞行中跟踪(内存)事务的常用机制是 scoreboarding

    从 Kepler(计算能力 3.x)开始的新一代 GPU 使用嵌入在着色器汇编代码中的控制字形式的一些帮助。虽然再次没有记录,但 Scott Gray 为他的 Maxas Maxwell 汇编程序对这些进行了逆向工程。他发现(除其他外)控制字包含用于跟踪内存事务的屏障指令,并且非常友好地在他的Control-Codes wiki 页面上记录了他的发现。

    【讨论】:

    • 感谢您的回复,很抱歉没有让我的问题更清楚。我想了解更多关于“跟踪内存访问进度的单独硬件”。您在回答中提到。我已按照建议更新了我的原始查询。
    • 我已更新答案以匹配更改后的问题。
    • 谢谢你,Tera,都明白了。我还有一个问题。 SMX 中的 LDST 内核,它们是否只计算要获取的有效地址?可以用来做定点算术加减法吗?
    • 根据他们的SASS instruction list,Maxwell和Pascal有一个LEA“加载有效地址”的指令。由于它没有在 PTX 中公开,因此您必须进行实验以查看是否以及如何生成它。
    • 鉴于它的无证状态,不清楚它有什么好处,如果它可以用当前的工具链生成。如果您想在单个指令中将 32 位整数添加到 64 位整数,我推测 LEA 指令可能会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多