2010-02-01 28 views
9

我正在尝试编写一个利用CUDA来执行粒子位置更新的简单粒子系统。现在我正在定义一个粒子,其中一个对象的位置由三个浮点值定义,而一个速度也由三个浮点值定义。当更新粒子时,我将为速度的Y分量添加一个常数值来模拟重力,然后将速度添加到当前位置以提供新位置。在内存管理方面,最好是维护两个单独的浮点数组来存储数据或以面向对象的方式进行构造。是这样的:如何在CUDA应用程序中构建数据以获得最佳速度

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

struct Particle 
{ 
    Vector position; 
    Vector velocity; 
}; 

这似乎是数据的大小是用任一方法(每个浮子4个字节,每向量3个浮筒,每粒子共计24个字节总共2个载体)这似乎是OO相同方法将允许CPU和GPU之间更高效的数据传输,因为我可以使用单个内存复制语句而不是2个(并且从长远来看更多,因为还有其他一些关于粒子的信息,比如Age ,生命期,重量/质量,温度等)然后,这些也只是代码的简单易读性和易于处理它,这也使我倾向于面向对象方法。但是我看到的例子并没有利用结构化数据,所以它让我怀疑这是否是一个原因。

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

+1

Err ..为什么不尝试找出? – 2010-02-01 19:58:44

+4

大家好。因为我对这个理论感兴趣,即使我发现一个比另一个更好,我仍然想知道为什么。 – 2010-02-01 20:07:25

回答

18

在“数组并行编程”(SOA)与“结构数组”(AOS)的讨论中,数据并行编程中很常见,其中您的两个示例中的第一个是AOS,第二个是SOA。许多并行编程范例,特别是SIMD风格的范例,都会选择SOA。

在GPU编程中,SOA通常首选的原因是优化对全局内存的访问。您可以在去年GTC的Advanced CUDA C上查看录制的演示文稿,详细描述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%)。

还有一种可能性 - 如果你在结构中有两个或四个浮标,那么你可以用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呈现的细节。

+0

汤姆,是否可以下载你链接的演示文稿? – 2010-02-02 18:46:59

+0

John,您可以使用以下链接之一:http://www.nvidia.com/content/GTC/videos/GTC09-1086.flv http://www.nvidia.com/content/GTC/videos/GTC09 -1086.mp4 – Tom 2010-02-02 21:10:07

相关问题