hedgefund

zig_particle_SIMD

Jan 8th, 2025
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.61 KB | Source Code | 0 0
  1. const std = @import("std");
  2. const print = std.debug.print;
  3. const mem = std.mem;
  4. const tMilli = std.time.milliTimestamp;
  5. const math = std.math;
  6. const rand = std.rand;
  7. const testing = std.testing;
  8.  
  9. const NUM_PARTICLES = 100000;
  10. const SIMD_WIDTH: usize = 8; // AVX equivalent for 256-bit
  11. const GRAVITY: f32 = -9.81;
  12. const DELTA_TIME: f32 = 0.01;
  13. const FIXED_SEED: u64 = 12345;
  14. const Vector = @Vector(SIMD_WIDTH, f32);
  15.  
  16. // Structure to hold particle data
  17. pub const ParticleData = struct {
  18.     positions_x: []f32,
  19.     positions_y: []f32,
  20.     positions_z: []f32,
  21.     velocities_x: []f32,
  22.     velocities_y: []f32,
  23.     velocities_z: []f32,
  24.     accelerations_x: []f32,
  25.     accelerations_y: []f32,
  26.     accelerations_z: []f32,
  27.     masses: []f32,
  28. };
  29.  
  30. pub fn allocateParticleData(allocator: mem.Allocator) !ParticleData {
  31.     const positions_x = try allocator.alloc(f32, NUM_PARTICLES);
  32.     const positions_y = try allocator.alloc(f32, NUM_PARTICLES);
  33.     const positions_z = try allocator.alloc(f32, NUM_PARTICLES);
  34.     const velocities_x = try allocator.alloc(f32, NUM_PARTICLES);
  35.     const velocities_y = try allocator.alloc(f32, NUM_PARTICLES);
  36.     const velocities_z = try allocator.alloc(f32, NUM_PARTICLES);
  37.     const accelerations_x = try allocator.alloc(f32, NUM_PARTICLES);
  38.     const accelerations_y = try allocator.alloc(f32, NUM_PARTICLES);
  39.     const accelerations_z = try allocator.alloc(f32, NUM_PARTICLES);
  40.     const masses = try allocator.alloc(f32, NUM_PARTICLES);
  41.  
  42.     return ParticleData{
  43.         .positions_x = positions_x,
  44.         .positions_y = positions_y,
  45.         .positions_z = positions_z,
  46.         .velocities_x = velocities_x,
  47.         .velocities_y = velocities_y,
  48.         .velocities_z = velocities_z,
  49.         .accelerations_x = accelerations_x,
  50.         .accelerations_y = accelerations_y,
  51.         .accelerations_z = accelerations_z,
  52.         .masses = masses,
  53.     };
  54. }
  55.  
  56. pub fn initializeParticles(data: *ParticleData) void {
  57.     // var rng = rand.DefaultPrng.init(@as(u64, @bitCast(tMilli())));
  58.     var rng = rand.DefaultPrng.init(FIXED_SEED);
  59.     for (0..NUM_PARTICLES) |i| {
  60.         data.positions_x[i] = rng.random().float(f32) * 10.0;
  61.         data.positions_y[i] = rng.random().float(f32) * 10.0;
  62.         data.positions_z[i] = rng.random().float(f32) * 10.0;
  63.  
  64.         data.velocities_x[i] = rng.random().float(f32) * 2.0 - 1.0;
  65.         data.velocities_y[i] = rng.random().float(f32) * 2.0 - 1.0;
  66.         data.velocities_z[i] = rng.random().float(f32) * 2.0 - 1.0;
  67.  
  68.         data.accelerations_x[i] = 0.0;
  69.         data.accelerations_y[i] = 0.0;
  70.         data.accelerations_z[i] = 0.0;
  71.  
  72.         data.masses[i] = rng.random().float(f32) * 2.0 + 1.0;
  73.     }
  74. }
  75.  
  76. fn freeParticleData(allocator: mem.Allocator, data: *ParticleData) void {
  77.   inline for (std.meta.fields(ParticleData)) |field| {
  78.        allocator.free(@field(data, field.name));
  79.     }
  80. }
  81.  
  82. fn loadVector(ptr: []f32, i: usize) Vector {
  83.     return @as(Vector, ptr[i*SIMD_WIDTH..][0..SIMD_WIDTH].*);
  84. }
  85.  
  86. fn storeVector(ptr: []f32, i: usize, vec: Vector) void {
  87.     @as(*align(1) @Vector(SIMD_WIDTH, f32), @ptrCast(ptr[i*SIMD_WIDTH..][0..SIMD_WIDTH].ptr)).* = vec;
  88. }
  89.  
  90. fn updateParticlesSimd(data: *ParticleData) void {
  91.     const gravity_vector: Vector = @splat(GRAVITY);
  92.     const delta_time_vector: Vector = @splat(DELTA_TIME);
  93.  
  94.     for (0..NUM_PARTICLES / SIMD_WIDTH) |i| {
  95.      
  96.         // Load data
  97.         const px = loadVector(data.positions_x, i);
  98.         const py = loadVector(data.positions_y, i);
  99.         const pz = loadVector(data.positions_z, i);
  100.         const vx = loadVector(data.velocities_x, i);
  101.         const vy = loadVector(data.velocities_y, i);
  102.         const vz = loadVector(data.velocities_z, i);
  103.         const ax = loadVector(data.accelerations_x, i);
  104.         const ay = loadVector(data.accelerations_y, i);
  105.         var az = loadVector(data.accelerations_z, i);
  106.  
  107.         // Update accelerations (gravity)
  108.         az = az + gravity_vector;
  109.  
  110.         // Update velocities
  111.         const nvx: Vector = vx + ax * delta_time_vector;
  112.         const nvy: Vector = vy + ay * delta_time_vector;
  113.         const nvz: Vector = vz + az * delta_time_vector;
  114.  
  115.         // Update positions
  116.         const npx: Vector = px + nvx * delta_time_vector;
  117.         const npy: Vector = py + nvy * delta_time_vector;
  118.         const npz: Vector = pz + nvz * delta_time_vector;
  119.  
  120.         // Store results
  121.         storeVector(data.positions_x, i, npx);
  122.         storeVector(data.positions_y, i, npy);
  123.         storeVector(data.positions_z, i, npz);
  124.         storeVector(data.velocities_x, i, nvx);
  125.         storeVector(data.velocities_y, i, nvy);
  126.         storeVector(data.velocities_z, i, nvz);
  127.         storeVector(data.accelerations_x, i, ax);
  128.         storeVector(data.accelerations_y, i, ay);
  129.         storeVector(data.accelerations_z, i, az);
  130.     }
  131. }
  132.  
  133. pub fn main() !void {
  134.  
  135.     const allocator = std.heap.page_allocator;
  136.  
  137.     var particle_data = try allocateParticleData(allocator);
  138.     defer freeParticleData(allocator, &particle_data);
  139.     initializeParticles(&particle_data);
  140.  
  141.     const num_steps: i32 = 100;
  142.  
  143.     // Time SIMD version
  144.     print("Starting SIMD test...\n", .{});
  145.     const start_simd = tMilli();
  146.     for (0..num_steps) |_| {
  147.         updateParticlesSimd(&particle_data);
  148.     }
  149.     const end_simd = tMilli();
  150.     const time_simd = @as(f32, @floatFromInt(end_simd - start_simd));
  151.     print("SIMD Time: {d:.2} ms\n", .{time_simd});
  152.  
  153.     print("First position Zig: x={d:.4}, y={d:.4}, z={d:.4}\n", .{
  154.         particle_data.positions_x[0],
  155.         particle_data.positions_y[0],
  156.         particle_data.positions_z[0],
  157.     });
  158. }
  159.  
Advertisement
Add Comment
Please, Sign In to add comment