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);
    }
}