Upload kernels/benchmark_satu1.cpp with huggingface_hub
Browse files- kernels/benchmark_satu1.cpp +85 -0
kernels/benchmark_satu1.cpp
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// benchmark_satu1.cpp — IKNN-Rl1-A1 — Combined benchmark SatU1 AVX2 vs AVX-512
|
| 2 |
+
// Version: v1.0
|
| 3 |
+
// Created: 2026-09-03T17:00:00+07:00
|
| 4 |
+
// Status: PUBLISHABLE — EN ONLY
|
| 5 |
+
// Repo: IKNN-Rl1-A1
|
| 6 |
+
|
| 7 |
+
#include "satu1_common.h"
|
| 8 |
+
#include <iostream>
|
| 9 |
+
#include <random>
|
| 10 |
+
#include <chrono>
|
| 11 |
+
#include <cmath>
|
| 12 |
+
|
| 13 |
+
// Declare functions from other translation units (we include via header but need extern)
|
| 14 |
+
// Instead include cpp directly for simplicity in this benchmark
|
| 15 |
+
#include "satu1_avx2.cpp"
|
| 16 |
+
#include "satu1_avx512.cpp"
|
| 17 |
+
|
| 18 |
+
int main() {
|
| 19 |
+
using namespace iknn::satu1;
|
| 20 |
+
|
| 21 |
+
std::cout << "=== IKNN-Rl1-A1 — SatU1 Kernel Benchmark — M1 ===" << std::endl;
|
| 22 |
+
std::cout << "Repo: IKNN-Rl1-A1 — Integrated Knowledge-phase Neural Network — Recursive Language Iteration 1 — Architecture 1" << std::endl;
|
| 23 |
+
std::cout << "Hardware: Xeon AVX-512 (VPOPCNTDQ, VBMI2) + Ryzen5 5650U AVX2 reference" << std::endl;
|
| 24 |
+
std::cout << "Timestamp: " << __DATE__ << " " << __TIME__ << std::endl;
|
| 25 |
+
|
| 26 |
+
std::mt19937_64 rng(12345);
|
| 27 |
+
const int WORDS = 8; // 512 weights
|
| 28 |
+
uint64_t act[WORDS], w[WORDS];
|
| 29 |
+
for (int i = 0; i < WORDS; ++i) {
|
| 30 |
+
act[i] = rng();
|
| 31 |
+
w[i] = rng();
|
| 32 |
+
}
|
| 33 |
+
float alpha = 0.75f;
|
| 34 |
+
|
| 35 |
+
// Correctness
|
| 36 |
+
float naive = compute_satu1_block_naive(act, w, alpha, WORDS);
|
| 37 |
+
float avx2 = avx2::compute_satu1_block_avx2(act, w, alpha, WORDS);
|
| 38 |
+
float avx512 = avx512::compute_satu1_block_avx512(act, w, alpha, WORDS);
|
| 39 |
+
|
| 40 |
+
std::cout << "[Correctness] Naive: " << naive << " AVX2: " << avx2 << " AVX-512: " << avx512 << std::endl;
|
| 41 |
+
bool pass = (std::abs(naive-avx2) < 1e-3f) && (std::abs(naive-avx512) < 1e-3f);
|
| 42 |
+
std::cout << (pass ? "[PASS] All kernels match naive" : "[FAIL] Mismatch") << std::endl;
|
| 43 |
+
if (!pass) return 1;
|
| 44 |
+
|
| 45 |
+
// Benchmark AVX2
|
| 46 |
+
{
|
| 47 |
+
const int ITERS = 2000000;
|
| 48 |
+
auto start = std::chrono::high_resolution_clock::now();
|
| 49 |
+
float sum = 0;
|
| 50 |
+
for (int it = 0; it < ITERS; ++it) {
|
| 51 |
+
act[0] ^= it;
|
| 52 |
+
sum += avx2::compute_satu1_block_avx2(act, w, alpha, WORDS);
|
| 53 |
+
}
|
| 54 |
+
auto end = std::chrono::high_resolution_clock::now();
|
| 55 |
+
double ms = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
|
| 56 |
+
double giga = (double)ITERS * WORDS * 64 / 1e9;
|
| 57 |
+
std::cout << "[BENCH AVX2] Iters " << ITERS << " Time " << ms << "ms Giga-popcnt/s " << giga/(ms/1000.0) << " sum " << sum << std::endl;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
// Benchmark AVX-512
|
| 61 |
+
{
|
| 62 |
+
const int ITERS = 2000000;
|
| 63 |
+
auto start = std::chrono::high_resolution_clock::now();
|
| 64 |
+
float sum = 0;
|
| 65 |
+
for (int it = 0; it < ITERS; ++it) {
|
| 66 |
+
act[0] ^= it;
|
| 67 |
+
sum += avx512::compute_satu1_block_avx512(act, w, alpha, WORDS);
|
| 68 |
+
}
|
| 69 |
+
auto end = std::chrono::high_resolution_clock::now();
|
| 70 |
+
double ms = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
|
| 71 |
+
double giga = (double)ITERS * WORDS * 64 / 1e9;
|
| 72 |
+
double tps_equiv = ITERS / (ms/1000.0);
|
| 73 |
+
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;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
// Memory bandwidth estimation
|
| 77 |
+
// Per token: 0.70GB read (SatU1 2.66GB*16% + NoeSA 0.97GB*20%)
|
| 78 |
+
// DDR4 38GB/s -> 54 TPS upper, DDR5 70GB/s -> 100 TPS upper
|
| 79 |
+
std::cout << "[BANDWIDTH] Estimated per token read 0.70GB" << std::endl;
|
| 80 |
+
std::cout << "[BANDWIDTH] Ryzen5 DDR4 38GB/s -> 54 TPS upper bound" << std::endl;
|
| 81 |
+
std::cout << "[BANDWIDTH] Xeon DDR5 70GB/s -> 100 TPS upper bound" << std::endl;
|
| 82 |
+
std::cout << "[TARGET] Ryzen5 28-42 / 60-85 TPS, AVX-512 65-90 / 120-165 TPS" << std::endl;
|
| 83 |
+
|
| 84 |
+
return 0;
|
| 85 |
+
}
|