Memory 在NVIDIA CUDA中访问整数值时具有良好的内存使用习惯

Memory 在NVIDIA CUDA中访问整数值时具有良好的内存使用习惯,memory,cuda,Memory,Cuda,我对CUDA编程一无所知,我想确保我了解一些与内存相关的基本原理,因为我对自己的一些想法有点困惑 我正在进行模拟,使用数十亿个一次性使用0到50范围内的随机数 在cuRand用随机的0.0到1.0浮点值填充一个巨大的数组之后,我运行一个内核,将所有这些浮点值数据转换为所需的整数范围。据我所知,我有一种感觉,因为全局内存的带宽非常低,所以只使用6位在一个无符号整数上存储5个这些值会更好。所以我做了 现在我必须存储大约20000个只读的yes/no值,这些值将被随机访问,假设基于随机值进入模拟的概率

我对CUDA编程一无所知,我想确保我了解一些与内存相关的基本原理,因为我对自己的一些想法有点困惑

我正在进行模拟,使用数十亿个一次性使用0到50范围内的随机数

在cuRand用随机的0.0到1.0浮点值填充一个巨大的数组之后,我运行一个内核,将所有这些浮点值数据转换为所需的整数范围。据我所知,我有一种感觉,因为全局内存的带宽非常低,所以只使用6位在一个无符号整数上存储5个这些值会更好。所以我做了

现在我必须存储大约20000个只读的yes/no值,这些值将被随机访问,假设基于随机值进入模拟的概率相同

首先,我想到了共享内存。使用一个比特看起来很棒,直到我意识到一个银行中的信息越多,冲突就越多。因此,解决方案似乎是使用无符号短(2Byte->40KB总计)来表示一个是/否信息,使用最大可用内存,从而最小化不同线程读取同一存储库的概率

另一个想法来自使用恒定内存和一级缓存。在这里,据我所知,这种方法与共享内存完全相反。现在需要通过更多线程读取同一位置,因此在一个4B组上放置32个值是最佳选择

因此,基于总体概率,我应该在共享内存和缓存之间做出决定,共享位置可能会更好,因为有这么多是/否值,每个块只有几十个或数百个线程,所以不会有太多的内存组冲突

但我对这个问题的总体理解正确吗?与内存相比,处理器真的那么快吗?优化内存访问是至关重要的,而在通过像、=、&=这样的操作提取数据时,考虑额外的指令并不重要


很抱歉有这么多的文字,我有无数种方法可以使模拟工作,但只有一些方法可以使它正确。我只是不想一次又一次地重复一些愚蠢的错误,因为我对某些东西理解得很糟糕。

任何CUDA程序员的前两个优化优先事项是:

  • 启动足够的线程(即公开足够的并行性),使机器有足够的工作来隐藏延迟

  • 有效利用内存

  • 上面的第二项将根据您使用的GPU内存类型提供各种指导,例如:

  • 努力实现对全局内存的联合访问
  • 利用缓存和共享内存优化数据的重用
  • 对于共享内存,争取非银行冲突访问
  • 对于恒定内存,争取统一访问(在给定的访问周期内,从同一位置读取扭曲中的所有线程)
  • 考虑使用纹理缓存和其他特殊的GPU功能
  • 你的问题集中在记忆上:

    与内存相比,处理器真的那么快吗?优化内存访问是至关重要的,而在通过像、=、&=这样的操作提取数据时,考虑额外的指令并不重要

    优化内存访问通常对于拥有在GPU上快速运行的代码非常重要。我给出的上述大多数建议/指导原则都不是针对每个
    int
    (或其他一些单词数量)应该打包多个数据项的想法,但是对于内存受限的代码,这样做并不是不可能的。GPU上的许多程序最终都会受到内存限制(即,它们对内存的使用最终是性能限制,而不是GPU上计算资源的使用)

    一个领域的例子是,开发人员在深入学习空间中,特别是在GPU上使用卷积神经网络,每个单词数量打包多个数据项。开发人员发现,在某些情况下,他们可以通过以下方式使培训代码运行得更快:

  • 将数据集存储为GPU内存中压缩的
    一半(16位浮点)量
  • 以压缩形式加载数据集
  • 拆包(并转换)每套包装的2
    half
    数量为2
    float
    数量
  • float
    数量执行计算
  • float
    结果转换为
    half
    并打包
  • 储存包装好的数量
  • 为下一个培训周期重复此过程
  • (有关
    half
    数据类型的其他背景信息,请参阅。)

    关键是,高效使用内存是使代码在GPU上快速运行的一个高度优先事项,这可能包括在某些情况下使用压缩量

    它是否适合您的情况可能是您必须进行基准测试和比较以确定对代码的影响

    阅读您的问题的其他一些评论:

    在这里,据我所知,这种方法与共享内存完全相反

  • 在某些方面,从访问模式的角度来看,共享内存和常量内存的使用是“相反的”。如前所述,有效使用恒定内存需要统一访问。在统一访问的情况下,共享内存也应该运行良好,因为它具有广播功能。您担心共享内存中的内存组冲突是对的,但较新GPU上的共享内存具有广播功能,当访问从同一实际位置而不是仅从同一个内存组进行时,该功能可消除内存组冲突问题。这些细微差别在许多其他关于共享内存的问题中都有涉及,所以我在这里不再深入讨论

  • >P>因为你把5个整数(0…50)打包成一个单一的代码> int <代码>,你也可以考虑(也许你已经这么做了)。