多线程内存访问是否比单线程内存访问更快?
假设我们使用的是C语言.一个简单的例子如下.如果我有一个巨大的数组A,我想复制A到B相同大小的数组A.使用多线程比单线程更快地进行内存复制吗?有多少线程适合进行这种内存操作?
编辑:让我把问题缩小.首先,我们不考虑GPU案例.当我们进行GPU编程时,内存访问优化非常重要和有效.根据我的经验,我们总是需要小心内存操作.另一方面,当我们处理CPU时并非总是如此.另外,我们不要考虑SIMD指令,例如avx和sse.当程序具有太多的内存访问操作而不是大量的计算操作时,这些也将显示内存性能问题.假设我们使用1-2个CPU来运行x86架构.每个CPU都有多个内核和一个四通道内存接口.主内存是DDR4,因为它在今天很常见.
我的数组是一个双精度浮点数的数组,其大小类似于CPU的L3缓存大小,大约为50MB.现在,我有两种情况:1)通过执行元素副本或使用memcpy将此数组复制到具有相同大小的另一个数组.2)将许多小阵列组合成这个巨大的阵列.两者都是实时操作,这意味着它们需要尽可能快地完成.多线程是否提供加速或下拉?在这种情况下影响内存操作性能的因素是什么?
有人说它主要依赖于DMA性能.我想是在我们做memcpy的时候.如果我们进行逐元素复制,首先会通过CPU缓存怎么办?
当我们在PC上创建OpenGL上下文时,有没有办法选择使用哪个物理设备或使用了多少设备?最新的OpenGL(4.5)API是否支持多GPU架构?如果我有两个相同的显卡(例如,两个Nvidia GeForce显卡),我如何正确编程OpenGL API以获得我有两张卡的好处?如何以最小的努力将OpenGL程序从单GPU版本转移到多GPU版本?
当我尝试将 OpenGL 实现迁移到 Vulkan 时,我发现 Vulkan 不支持“uniformatomic_uint”。我的用例很简单:在所有片段中递增一个整数。我试图搜索解决方案,但没有找到任何最新的解决方案。
以下是旧解决方案的列表:
https://software.intel.com/en-us/articles/opengl-performance-tips-atomic-counter-buffers-versus-shader-storage-buffer-objects。据说OpenGL原子计数器类似于SSBO原子操作,并且在某些平台上可能会实现为SSBO原子操作。(不确定今天是否仍然如此)。
https://community.khronos.org/t/vulkan-atomic-counters/7146。它还表示可以使用 SSBO 上的图像加载/存储或原子操作作为替代。(但内容是 2 年前的。)
由于 Vulkan 仍在不断发展,任何人都可以建议一种最新的标准方法,在 Vulkan 中使用 GLSL 对整数进行原子增量吗?
编辑:
我已经得到了答案,但我会添加更多细节。在我的 OpenGL 代码中,我有一个带有顶点着色器和片段着色器的渲染通道(不涉及计算着色器)。在片段着色器中,我有以下 glsl (简化):
#version 450
layout (binding = 0) uniform atomic_uint fragmentCount;
void main()
{
atomicCounterIncrement(fragmentCount);
}
Run Code Online (Sandbox Code Playgroud)
该着色器在 OpenGL 中运行良好,因为 OpenGL 在 glBindBuffer 中具有枚举“GL_ATOMIC_COUNTER_BUFFER”,在 glsl 中具有关键字“atomic_uint”。然而,Vulkan没有相应的内置关键字。因此,我尝试寻找替代品。我没有询问如何查询正在渲染的片段数量,尽管这里的着色器看起来像是我正在这样做。我想知道 Vulkan 中是否存在通用图形着色器中的“原子计数器”。正如 Nicol Bolas 指出的,Vulkan 中没有这样的东西,而且硬件方面也没有在 NVIDIA GPU 上实现,所以我决定使用 SSBO 和 AtomicAdd 来做同样的事情。
希望这能让我的问题更清楚。
据我所知,当我们通过"vkUpdateDescriptorSets"更新统一变量时,相应命令缓冲区的状态将无效.因此,我们必须重置命令缓冲区并重新记录它.
有没有办法更新统一变量而不对命令缓冲区做任何事情?
更新每帧统一变量数据的最佳方法是什么(在性能方面)?