2010-02-01 7 views
9

Estoy intentando escribir un sistema de partículas simple que aprovecha CUDA para actualizar las posiciones de las partículas. En este momento estoy definiendo que una partícula tiene un objeto con una posición definida con tres valores de flotación, y una velocidad también definida con tres valores de flotación. Al actualizar las partículas, agrego un valor constante a la componente Y de la velocidad para simular la gravedad, luego sumar la velocidad a la posición actual para obtener la nueva posición. En términos de gestión de memoria, es mejor mantener dos matrices separadas de flotadores para almacenar los datos o estructurarlos de forma orientada a objetos. Algo como esto:Cómo estructurar datos para velocidad óptima en una aplicación CUDA

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

struct Particle 
{ 
    Vector position; 
    Vector velocity; 
}; 

Parece que el tamaño de los datos es el mismo con cualquiera de los métodos (4 bytes por flotador, 3 flotadores por Vector, 2 vectores por partícula total de 24 bytes en total) Parece que el OO El enfoque permitiría una transferencia de datos más eficiente entre la CPU y la GPU porque podría usar una sola declaración de copia de memoria en lugar de 2 (y a la larga más, ya que hay algunos otros bits de información sobre partículas que serán relevantes, como Age , Lifetime, Weight/Mass, Temperature, etc.) Y también existe la simple legibilidad del código y la facilidad de manejo que también me inclina hacia el enfoque OO. Pero los ejemplos que he visto no utilizan datos estructurados, por lo que me pregunto si hay alguna razón.

Entonces, la pregunta es ¿qué es mejor: matrices individuales de datos u objetos estructurados?

+1

Err .. ¿por qué no intentarlo y descubrirlo? –

+4

Lol. Como estoy interesado en la teoría, incluso si encuentro que una funciona mejor que la otra, aún quiero saber por qué. –

Respuesta

18

Es común en la programación paralela de datos hablar de "Estructura de matrices" (SOA) frente a "Array of Structs" (AOS), donde el primero de sus dos ejemplos es AOS y el segundo es SOA. Muchos paradigmas de programación paralela, en particular paradigmas estilo SIMD, preferirán SOA.

En la programación de GPU, la razón por la que normalmente se prefiere SOA es optimizar los accesos a la memoria global. Puede ver la presentación grabada en Advanced CUDA C de GTC el año pasado para obtener una descripción detallada de cómo la GPU accede a la memoria.

El punto principal es que las transacciones de memoria tienen un tamaño mínimo de 32 bytes y desea maximizar la eficiencia de cada transacción.

Con 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 

Con 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 

En el segundo caso, la lectura de direcciones consecutivas significa que tiene 100% de eficacia frente al 33% en el primer caso. Tenga en cuenta que en las GPU antiguas (capacidad de cálculo 1.0 y 1.1) la situación es mucho peor (13% de eficiencia).

Hay otra posibilidad - si ha tenido dos o cuatro flotadores en la estructura entonces se podría leer el AOS con una eficiencia del 100%:

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

Una vez más, echa un vistazo a la presentación avanzada CUDA C para los detalles .

+0

Tom, ¿es posible descargar la presentación que vinculó? –

+0

John, puede usar uno de los siguientes enlaces: http://www.nvidia.com/content/GTC/videos/GTC09-1086.flv http://www.nvidia.com/content/GTC/videos/GTC09 -1086.mp4 – Tom

Cuestiones relacionadas