sample\basic\sample_simd.hsp » Plain Format
;============================================================
; sample_simd.hsp — SSE/AVX SIMD ベンチマーク
;
; 1,000,000 要素の double 配列に対する
; (A) HSP スカラループ (for i ... : out(i) = a(i)+b(i))
; (B) iron_simd_add_d (プラグイン SIMD)
; の実行時間を計測して比較。ついで sum / dot / matmul も実演。
;============================================================
#include "iron_simd.hsp"
title "iron_simd benchmark"
screen 0, 640, 600
objmode 2
font "MS Gothic", 14
; ---- CPU 機能表示 ---------------------------------------
iron_simd_cpu_name cpu_name
iron_simd_features feat
mes "CPU : " + cpu_name
mes "SIMD: " + feat
mes ""
N = 1000000
mes "要素数 N = " + N
ddim a, N
ddim b, N
ddim c, N
; ランダム風の値で初期化
randomize 1234
repeat N
a(cnt) = double(cnt & 1023) / 1024.0
b(cnt) = double((cnt * 7) & 1023) / 1024.0
loop
; =========================================================
; (A) スカラ (純 HSP ループ)
; tick = gettime(7) (ms) + gettime(6) (sec) * 1000
; =========================================================
t0 = gettime(7) + gettime(6) * 1000
repeat N
c(cnt) = a(cnt) + b(cnt)
loop
t1 = gettime(7) + gettime(6) * 1000
scalar_ms = t1 - t0
if scalar_ms < 0 : scalar_ms += 60000 ; 分またぎ簡易補正
; 参照値
ref_c0 = c(0)
ref_c_last = c(N - 1)
; =========================================================
; (B) SIMD (iron_simd_add_d)
; =========================================================
; c をゼロに戻してから
repeat N : c(cnt) = 0.0 : loop
t0 = gettime(7) + gettime(6) * 1000
iron_simd_add_d a, b, c, N
t1 = gettime(7) + gettime(6) * 1000
simd_ms = t1 - t0
if simd_ms < 0 : simd_ms += 60000
; 結果検証
simd_c0 = c(0)
simd_c_last = c(N - 1)
mes ""
mes "=== add_d ベンチマーク ==="
mes strf(" scalar HSP loop : %5d ms", scalar_ms)
mes strf(" iron_simd_add_d : %5d ms", simd_ms)
if simd_ms > 0 {
mes strf(" speedup : x %.2f", double(scalar_ms) / double(simd_ms))
}
mes ""
mes strf(" c[0] scalar=%.6f simd=%.6f", ref_c0, simd_c0)
mes strf(" c[N-1] scalar=%.6f simd=%.6f", ref_c_last, simd_c_last)
; =========================================================
; sum / dot
; =========================================================
t0 = gettime(7) + gettime(6) * 1000
iron_simd_sum_d a, N, s
t1 = gettime(7) + gettime(6) * 1000
sum_ms = t1 - t0 : if sum_ms < 0 : sum_ms += 60000
t0 = gettime(7) + gettime(6) * 1000
iron_simd_dot_d a, b, N, dot
t1 = gettime(7) + gettime(6) * 1000
dot_ms = t1 - t0 : if dot_ms < 0 : dot_ms += 60000
mes ""
mes "=== 集約演算 ==="
mes strf(" sum = %.4f (%d ms)", s, sum_ms)
mes strf(" dot = %.4f (%d ms)", dot, dot_ms)
iron_simd_min_d a, N, vmin
iron_simd_max_d a, N, vmax
mes strf(" min = %.4f", vmin)
mes strf(" max = %.4f", vmax)
; =========================================================
; 行列積 (64x64 * 64x64 = 64x64 float)
; =========================================================
M = 64 : NN = 64 : K = 64
sdim mA, 4 * M * NN
sdim mB, 4 * NN * K
sdim mC, 4 * M * K
; 行列に float を詰める (lpoke 相当; ここでは各要素を 1.0/255 刻みの簡易値に)
; iron_simd は float=32bit/要素 と期待するので、poke で int→float ビットキャスト
; を行う。ここでは簡便のため A, B をゼロ+対角 1 に設定:
repeat M * NN : poke mA, cnt * 4, 0 : poke mA, cnt * 4 + 1, 0 : poke mA, cnt * 4 + 2, 0 : poke mA, cnt * 4 + 3, 0 : loop
repeat NN * K : poke mB, cnt * 4, 0 : poke mB, cnt * 4 + 1, 0 : poke mB, cnt * 4 + 2, 0 : poke mB, cnt * 4 + 3, 0 : loop
; 対角成分を 1.0f (IEEE754: 0x3f800000) に設定
repeat M
if cnt < NN {
lpoke mA, (cnt * NN + cnt) * 4, 0x3f800000
}
loop
repeat NN
if cnt < K {
lpoke mB, (cnt * K + cnt) * 4, 0x3f800000
}
loop
t0 = gettime(7) + gettime(6) * 1000
iron_simd_matmul_f mA, mB, mC, M, NN, K
t1 = gettime(7) + gettime(6) * 1000
mm_ms = t1 - t0 : if mm_ms < 0 : mm_ms += 60000
c00 = lpeek(mC, 0) ; ビットパターン
c11 = lpeek(mC, (1 * K + 1) * 4)
mes ""
mes strf("=== matmul 64x64 float === (%d ms)", mm_ms)
mes strf(" C[0,0] bits = 0x%08x (1.0 の期待値 = 0x3f800000)", c00)
mes strf(" C[1,1] bits = 0x%08x", c11)
mes ""
mes "完了"
stop