CUDA 中每个块的数据——它是不是在一个事务中广播?

Posted

技术标签:

【中文标题】CUDA 中每个块的数据——它是不是在一个事务中广播?【英文标题】:data per block in CUDA -- does it broadcast in one transaction?CUDA 中每个块的数据——它是否在一个事务中广播? 【发布时间】:2012-09-03 16:48:11 【问题描述】:

我有一个每个块的数据数组。 我在 cuda Grid 中有 N 个块和一个大小为 N 的常量数据数组“block_data[]”。

因此,给定块“X”中的所有线程仅访问一次 block_data[X],并使用该值执行某些操作。

我的问题是:这种广播方案是否有效? 如果不是,我应该采取什么方法?

在 cmets 之后编辑:我对常量内存的唯一问题是它的大小有限,因为我可以拥有超过 64K 的块。这意味着超过 64KB

问候

【问题讨论】:

您是否修改了 cuda 内核中的 block_data ?如果不是,则将其分配在针对该类型的访问进行了精确优化的常量内存中是有意义的 它没有变化,实际上它是一个查找表。常量内存的唯一问题是整个内核执行的内存是 64KB,对吗? 是的,总共只有 64kb 的常量内存。顺便说一句,我记得如果地址不依赖于线程 ID(这可能是您的情况),Fermi GPU 还可以通过常量缓存(即加载统一)从全局内存中加载只读数据。因此,我认为如果您按原样使用 block_data 不会对性能产生任何影响 是的,大多数查找表都没有被常量内存很好地服务。 @asm 是对的,加载统一指令可能是你最好的选择。 是的,它是 ptx 指令。只需确保使用 const 限定符声明 block_array 即可。然后你可以检查生成的ptx代码,看看是否确实使用了load uniform 【参考方案1】:

如果您只使用普通的全局内存访问,那么事务的效率就相当低,尽管取决于您的内核所做的工作量,影响可能非常小。

我假设sizeof(block_data) 是一个字节(从您的问题推断“...可能有超过 64K 的块。这意味着超过 64KB”)。

如果操作缓存在 L1 中,那么您将获取 128 个字节以获得所需的一位信息 (sizeof(block_data)),如果块中的其他扭曲请求相同的数据,那么它们应该从 L1 获取。负载效率是 1/128,但你应该只为块支付一次。 如果操作未缓存在 L1 中(例如,您将“-dlcm=cg”传递给汇编器),那么您将获取 32 个字节。效率是 1/32,但您为每个经线支付一次。 一旦加载数据,它就会广播到 warp 中的所有线程。

另一种方法是将数据标记为const __restrict__,这向编译器表明数据是a) 只读的并且b) 没有任何其他指针的别名。由于编译器可以检测到访问是统一的,因此它可以优化访问以使用只读缓存之一(例如,常量缓存,或者,在计算能力 >=3.5 时,只读数据缓存也称为纹理缓存)。

【讨论】:

感谢 Tom,目前我使用 L1 对数组的每个元素 (int) 使用 4 个字节进行了测试。生成的 PTX 代码确实使用了“ldu”指令,但我希望它运行得更快。我在 Geforce gtx 680 上进行测试。我仍然需要测试您提到的其他选项(尝试 -dlcm=cg 并添加 'const restrict')。 仅报告结果:我尝试使用“restrict”并添加“-dlcm=cg”。性能与不使用它们时大致相同。【参考方案2】:

如果你想改变block_data[N]数组中的值,最好使用共享内存__shared__的概念。如果您不更改block_data[N] 的值,请使用__const__ 或使用缓存的概念。通过使用 L2 Cache,可以获得 1536KB 的内存(Kepler)。

【讨论】:

更新问题,block_data 是常量,只读取一次。 如果是一次读取,尝试使用二级缓存。它更快。如果使用 L1 缓存,共享内存和 L1 缓存共享 64KB 内存。 我唯一担心的是一次性阅读,我想在这种情况下我被缓存搞砸了。来自全局内存的经线广播怎么样,开普勒中是否存在?编辑:我会更详细地看看 L2 缓存 所以对于 L2(因为它默认打开),您实际上是指将数据留在全局内存中,然后从每个线程中读取公共值? (开普勒拱门下) 看看编程指南 4.2 中的 F.4 和 F.5。广播设备计算能力的变化。

以上是关于CUDA 中每个块的数据——它是不是在一个事务中广播?的主要内容,如果未能解决你的问题,请参考以下文章

CUDA - 多处理器、Warp 大小和每个块的最大线程数:确切的关系是啥?

可以在 CUDA 上启动的最大线程数

CUDA 扭曲和每个块的最佳线程数

CUDA:每个多处理器的线程数和每个块的线程数的区别是啥? [复制]

Oracle在块内是如何组织和管理数据的

你能以编程方式知道 GPU 中每个块的最大块数和线程数吗?