File size: 4,118 Bytes
be99550 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | use wgpu::util::DeviceExt;
use bytemuck::{Pod, Zeroable};
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct PackedPhaseU32 {
pub data: u32,
}
pub async fn execute_gpu_sync(tensor_data: &mut [u32], iterations: usize) {
let instance = wgpu::Instance::default();
let adapter = instance.request_adapter(&wgpu::RequestAdapterOptions::default()).await.unwrap();
let supported_limits = adapter.limits();
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
label: None,
required_features: wgpu::Features::empty(),
required_limits: supported_limits.clone(),
}, None).await.unwrap();
let data_byte_size = std::mem::size_of_val(tensor_data);
let max_buffer = supported_limits.max_storage_buffer_binding_size as usize;
let chunk_size = if data_byte_size > max_buffer {
max_buffer / 4
} else {
tensor_data.len()
};
// [ํจ์น ์๋ฃ] 100๋ง ๊ฐ๊ฐ ๋๋ ์ํฌ๊ทธ๋ฃน์ 2D ํ๋ฉด(X, Y)์ผ๋ก ์ ์ด์ ์ฒ๋ฆฌํ๋ WGSL ์
ฐ์ด๋
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(r#"
@group(0) @binding(0) var<storage, read_write> phases: array<u32>;
@compute @workgroup_size(256, 1, 1)
fn main(
@builtin(workgroup_id) group_id: vec3<u32>,
@builtin(local_invocation_id) local_id: vec3<u32>,
@builtin(num_workgroups) num_groups: vec3<u32>
) {
// 2D ๋์คํจ์น ๊ทธ๋ฃน ์ขํ๋ฅผ 1D ์ ํ ์ธ๋ฑ์ค๋ก ๋ณํ
let group_idx = group_id.y * num_groups.x + group_id.x;
let idx = group_idx * 256u + local_id.x;
if (idx >= arrayLength(&phases)) { return; }
let phase = phases[idx];
let context_signal = 0x0F0F0F0Fu;
let mask = 0x55555555u;
let diff = phase ^ context_signal;
let sync_pull = (diff & mask) >> 1u;
let pull_11 = sync_pull | (sync_pull << 1u);
phases[idx] = (phase & ~pull_11) | pull_11;
}
"#)),
});
let compute_pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: None,
layout: None,
module: &shader,
entry_point: "main",
});
let bind_group_layout = compute_pipeline.get_bind_group_layout(0);
for chunk in tensor_data.chunks_mut(chunk_size) {
let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Full Tensor Buffer"),
contents: bytemuck::cast_slice(chunk),
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC | wgpu::BufferUsages::COPY_DST,
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: buffer.as_entire_binding(),
}],
});
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
let total_threads = chunk.len() as u32;
let total_groups = (total_threads + 255) / 256;
// Vulkan ํ๊ณ(65535) ์ฐํ๋ฅผ ์ํ 2D ๋ถํ (Folding)
let max_groups_x = 65535;
let groups_x = total_groups.min(max_groups_x);
let groups_y = (total_groups + max_groups_x - 1) / max_groups_x;
for _ in 0..iterations {
let mut cpass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor::default());
cpass.set_pipeline(&compute_pipeline);
cpass.set_bind_group(0, &bind_group, &[]);
cpass.dispatch_workgroups(groups_x, groups_y, 1);
}
queue.submit(Some(encoder.finish()));
device.poll(wgpu::Maintain::Wait);
}
}
|