File size: 3,698 Bytes
3ac63cb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
// benchmark_satu1.cpp — IKNN-Rl1-A1 — Combined benchmark SatU1 AVX2 vs AVX-512
// Version: v1.0
// Created: 2026-09-03T17:00:00+07:00
// Status: PUBLISHABLE — EN ONLY
// Repo: IKNN-Rl1-A1

#include "satu1_common.h"
#include <iostream>
#include <random>
#include <chrono>
#include <cmath>

// Declare functions from other translation units (we include via header but need extern)
// Instead include cpp directly for simplicity in this benchmark
#include "satu1_avx2.cpp"
#include "satu1_avx512.cpp"

int main() {
    using namespace iknn::satu1;

    std::cout << "=== IKNN-Rl1-A1 — SatU1 Kernel Benchmark — M1 ===" << std::endl;
    std::cout << "Repo: IKNN-Rl1-A1 — Integrated Knowledge-phase Neural Network — Recursive Language Iteration 1 — Architecture 1" << std::endl;
    std::cout << "Hardware: Xeon AVX-512 (VPOPCNTDQ, VBMI2) + Ryzen5 5650U AVX2 reference" << std::endl;
    std::cout << "Timestamp: " << __DATE__ << " " << __TIME__ << std::endl;

    std::mt19937_64 rng(12345);
    const int WORDS = 8; // 512 weights
    uint64_t act[WORDS], w[WORDS];
    for (int i = 0; i < WORDS; ++i) {
        act[i] = rng();
        w[i] = rng();
    }
    float alpha = 0.75f;

    // Correctness
    float naive = compute_satu1_block_naive(act, w, alpha, WORDS);
    float avx2 = avx2::compute_satu1_block_avx2(act, w, alpha, WORDS);
    float avx512 = avx512::compute_satu1_block_avx512(act, w, alpha, WORDS);

    std::cout << "[Correctness] Naive: " << naive << " AVX2: " << avx2 << " AVX-512: " << avx512 << std::endl;
    bool pass = (std::abs(naive-avx2) < 1e-3f) && (std::abs(naive-avx512) < 1e-3f);
    std::cout << (pass ? "[PASS] All kernels match naive" : "[FAIL] Mismatch") << std::endl;
    if (!pass) return 1;

    // Benchmark AVX2
    {
        const int ITERS = 2000000;
        auto start = std::chrono::high_resolution_clock::now();
        float sum = 0;
        for (int it = 0; it < ITERS; ++it) {
            act[0] ^= it;
            sum += avx2::compute_satu1_block_avx2(act, w, alpha, WORDS);
        }
        auto end = std::chrono::high_resolution_clock::now();
        double ms = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
        double giga = (double)ITERS * WORDS * 64 / 1e9;
        std::cout << "[BENCH AVX2] Iters " << ITERS << " Time " << ms << "ms Giga-popcnt/s " << giga/(ms/1000.0) << " sum " << sum << std::endl;
    }

    // Benchmark AVX-512
    {
        const int ITERS = 2000000;
        auto start = std::chrono::high_resolution_clock::now();
        float sum = 0;
        for (int it = 0; it < ITERS; ++it) {
            act[0] ^= it;
            sum += avx512::compute_satu1_block_avx512(act, w, alpha, WORDS);
        }
        auto end = std::chrono::high_resolution_clock::now();
        double ms = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
        double giga = (double)ITERS * WORDS * 64 / 1e9;
        double tps_equiv = ITERS / (ms/1000.0);
        std::cout << "[BENCH AVX-512] Iters " << ITERS << " Time " << ms << "ms Giga-popcnt/s " << giga/(ms/1000.0) << " TPS equiv " << tps_equiv << " sum " << sum << std::endl;
    }

    // Memory bandwidth estimation
    // Per token: 0.70GB read (SatU1 2.66GB*16% + NoeSA 0.97GB*20%)
    // DDR4 38GB/s -> 54 TPS upper, DDR5 70GB/s -> 100 TPS upper
    std::cout << "[BANDWIDTH] Estimated per token read 0.70GB" << std::endl;
    std::cout << "[BANDWIDTH] Ryzen5 DDR4 38GB/s -> 54 TPS upper bound" << std::endl;
    std::cout << "[BANDWIDTH] Xeon DDR5 70GB/s -> 100 TPS upper bound" << std::endl;
    std::cout << "[TARGET] Ryzen5 28-42 / 60-85 TPS, AVX-512 65-90 / 120-165 TPS" << std::endl;

    return 0;
}