gpt4 book ai didi

c++ - 如何在 CUDA 应用程序中构建数据以获得最佳速度

转载 作者:可可西里 更新时间:2023-11-01 16:29:28 25 4
gpt4 key购买 nike

我正在尝试编写一个简单的粒子系统,它利用 CUDA 来更新粒子位置。现在我正在定义一个粒子,它有一个对象,其位置由三个浮点值定义,速度也由三个浮点值定义。更新粒子时,我向速度的 Y 分量添加一个常数值以模拟重力,然后将速度添加到当前位置以得出新位置。在内存管理方面,最好是维护两个独立的 float 组来存储数据或以面向对象的方式进行结构化。像这样:

struct Vector
{
float x, y, z;
};

struct Particle
{
Vector position;
Vector velocity;
};

这两种方法的数据大小似乎相同(每个 float 4 个字节,每个 vector 3 个 float ,每个粒子 2 个 vector ,总计 24 字节)似乎 OO 方法允许更有效的数据传输CPU 和 GPU,因为我可以使用单个内存复制语句而不是 2 个(从长远来看,更多,因为还有一些关于粒子的其他信息将变得相关,比如年龄、生命周期、重量/质量、温度等)然后还有代码的简单可读性和易于处理,这也让我倾向于 OO 方法。但是我看到的例子没有使用结构化数据,所以这让我想知道是否有原因。

所以问题是哪个更好:单独的数据数组还是结构化对象?

最佳答案

在数据并行编程中,谈论“数组结构”(SOA) 与“结构数组”(AOS) 是很常见的,您的两个示例中的第一个是 AOS,第二个是 SOA。许多并行编程范式,尤其是 SIMD 风格的范式,更喜欢 SOA。

在 GPU 编程中,通常首选 SOA 的原因是优化对全局内存的访问。您可以在 Advanced CUDA C 上查看录制的演示文稿来自去年的 GTC,详细描述了 GPU 如何访问内存。

要点是内存事务的最小大小为 32 字节,您希望最大限度地提高每个事务的效率。

使用 AOS:

position[base + tid].x = position[base + tid].x + velocity[base + tid].x * dt;
// ^ write to every third address ^ read from every third address
// ^ read from every third address

使用 SOA:

position.x[base + tid] = position.x[base + tid] + velocity.x[base + tid] * dt;
// ^ write to consecutive addresses ^ read from consecutive addresses
// ^ read from consecutive addresses

在第二种情况下,从连续地址读取意味着您有 100% 的效率,而在第一种情况下只有 33%。请注意,在较旧的 GPU(计算能力 1.0 和 1.1)上,情况更糟(13% 的效率)。

还有另一种可能性——如果结构中有两个或四个 float ,那么您可以 100% 的效率读取 AOS:

float4 lpos;
float4 lvel;
lpos = position[base + tid];
lvel = velocity[base + tid];
lpos.x += lvel.x * dt;
//...
position[base + tid] = lpos;

再次,查看高级 CUDA C 演示以了解详细信息。

关于c++ - 如何在 CUDA 应用程序中构建数据以获得最佳速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2179426/

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