File size: 4,918 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
// ๐Ÿ”ฌ ์‹ค์ œ ํ•˜๋“œ์›จ์–ด AI ๋ฐ ํ…์„œ ์—ฐ์‚ฐ ์‹ค์ธก ๋ฒค์น˜๋งˆํฌ ์Šค์œ„ํŠธ (src/bin/run_ai_benchmarks.rs)
use std::time::Instant;
use rayon::prelude::*;
use rand::Rng;

fn main() {
    println!("============================================================");
    println!(" ๐Ÿงช [์‹ค์ œ ๋กœ์ปฌ ํ•˜๋“œ์›จ์–ด] AI ๋ฐ ๋ณต์žก๊ณ„ ์„ฑ๋Šฅ ์‹ค์ธก ๋ฒค์น˜๋งˆํฌ");
    println!("============================================================\n");

    // -------------------------------------------------------------
    // 1. ํ–‰๋ ฌ ๊ณฑ์…ˆ (Dense MatMul / GFLOPS ์ธก์ •)
    // -------------------------------------------------------------
    println!("โ–ถ [ํ…Œ์ŠคํŠธ 1] ํ‘œ์ค€ ์‹ ๊ฒฝ๋ง ํ•ต์‹ฌ ์—ฐ์‚ฐ: 1024x1024 FP32 Dense MatMul");
    let n = 1024;
    let mut rng = rand::thread_rng();
    let a: Vec<f32> = (0..n * n).map(|_| rng.gen_range(-1.0..1.0)).collect();
    let b: Vec<f32> = (0..n * n).map(|_| rng.gen_range(-1.0..1.0)).collect();
    let mut c = vec![0.0f32; n * n];

    // ์›Œ๋ฐ์—…
    for i in 0..10 {
        c[i] = a[i] * b[i];
    }

    let start = Instant::now();
    // ๋ณ‘๋ ฌ ํƒ€์ผ๋ง ํ–‰๋ ฌ ๊ณฑ์…ˆ
    c.par_chunks_mut(n).enumerate().for_each(|(i, row)| {
        for k in 0..n {
            let a_val = a[i * n + k];
            for j in 0..n {
                row[j] += a_val * b[k * n + j];
            }
        }
    });
    let matmul_time = start.elapsed().as_secs_f64();
    let total_flops = 2.0 * (n as f64) * (n as f64) * (n as f64);
    let gflops = (total_flops / matmul_time) / 1e9;

    println!("   โ””โ”€ ์†Œ์š” ์‹œ๊ฐ„: {:.4} ์ดˆ | ์‹ค์ธก ์—ฐ์‚ฐ๋ ฅ: {:.2} GFLOPS\n", matmul_time, gflops);

    // -------------------------------------------------------------
    // 2. ์–ดํ…์…˜(Attention) ์—ฐ์‚ฐ ์‹œํ€€์Šค ๊ธธ์ด๋ณ„ ๋ ˆ์ดํ„ด์‹œ ์ธก์ •
    // -------------------------------------------------------------
    println!("โ–ถ [ํ…Œ์ŠคํŠธ 2] ํŠธ๋žœ์Šคํฌ๋จธ Self-Attention O(N^2) ์‹œํ€€์Šค๋ณ„ ์ง€์—ฐ์‹œ๊ฐ„");
    let d_head = 64;
    for &seq_len in &[512, 1024, 2048] {
        let q: Vec<f32> = (0..seq_len * d_head).map(|_| rng.gen_range(-1.0..1.0)).collect();
        let k: Vec<f32> = (0..seq_len * d_head).map(|_| rng.gen_range(-1.0..1.0)).collect();
        
        let start_att = Instant::now();
        // Attention Score: Q * K^T (seq_len x seq_len)
        let _scores: Vec<f32> = (0..seq_len).into_par_iter().flat_map(|i| {
            let mut row = vec![0.0f32; seq_len];
            let q_vec = &q[i * d_head..(i + 1) * d_head];
            for j in 0..seq_len {
                let k_vec = &k[j * d_head..(j + 1) * d_head];
                let mut dot = 0.0f32;
                for d in 0..d_head {
                    dot += q_vec[d] * k_vec[d];
                }
                row[j] = dot;
            }
            row
        }).collect();
        let att_dur = start_att.elapsed().as_secs_f64() * 1000.0;
        println!("   โ””โ”€ ์‹œํ€€์Šค ๊ธธ์ด {:4} ํ† ํฐ: ๋ ˆ์ดํ„ด์‹œ {:.2} ms", seq_len, att_dur);
    }
    println!();

    // -------------------------------------------------------------
    // 3. BioPhys 8-State ๋ณต์žก๊ณ„ ์—”์ง„ 100๋งŒ ๋…ธ๋“œ ์Šค์ผ€์ผ๋ง ์ธก์ •
    // -------------------------------------------------------------
    println!("โ–ถ [ํ…Œ์ŠคํŠธ 3] BioPhys 8-State ๋ณต์žก๊ณ„ ์—”์ง„ ์ฒ˜๋ฆฌ๋Ÿ‰ (์Šค์ผ€์ผ๋ณ„ ์‹ค์ธก)");
    for &grid_size in &[256, 512, 1024] {
        let total_nodes = grid_size * grid_size;
        let bedrock: Vec<f32> = vec![0.1f32; total_nodes];
        let mut topsoil: Vec<f32> = vec![0.5f32; total_nodes];

        let start_engine = Instant::now();
        for _ in 0..5 {
            let s = grid_size as i32;
            let next: Vec<f32> = (0..grid_size).into_par_iter().flat_map(|y| {
                let mut row = Vec::with_capacity(grid_size);
                for x in 0..grid_size {
                    let idx = y * grid_size + x;
                    let u = ((y as i32 - 1 + s) % s * s + x as i32) as usize;
                    let d = ((y as i32 + 1) % s * s + x as i32) as usize;
                    let l = (y as i32 * s + (x as i32 - 1 + s) % s) as usize;
                    let r = (y as i32 * s + (x as i32 + 1) % s) as usize;
                    let neighbor_e = (topsoil[u] + topsoil[d] + topsoil[l] + topsoil[r]) * 0.25;
                    row.push(neighbor_e + bedrock[idx]);
                }
                row
            }).collect();
            topsoil = next;
        }
        let dur = start_engine.elapsed().as_secs_f64();
        let updates = (total_nodes as f64 * 5.0) / dur;
        println!("   โ””โ”€ ๊ฒฉ์ž {:4}x{:4} ({:7} ๋…ธ๋“œ): ์ฒ˜๋ฆฌ๋Ÿ‰ {:.2} MCell/sec", grid_size, grid_size, total_nodes, updates / 1e6);
    }

    println!("\n============================================================");
    println!(" โœ… ์‹ค์ œ ๋กœ์ปฌ ํ•˜๋“œ์›จ์–ด ๋ฒค์น˜๋งˆํฌ ์ „ ํ•ญ๋ชฉ ์ธก์ • ์™„๋ฃŒ");
    println!("============================================================");
}