;;
;; benchmark-gpu-proper.scm - Proper GPU benchmark using sensory API
;;
;; Tests atomese-simd performance fixes:
;; 1. Binary caching (2.2x program load speedup)
;; 2. Dispatch thread build (eliminates per-session overhead)
;;
(use-modules (opencog) (opencog exec))
(use-modules (opencog sensory) (opencog opencl))
(use-modules (ice-9 format))
;; Helper: time execution in milliseconds
(define (time-ms thunk)
(let* ((start (get-internal-real-time))
(result (thunk))
(end (get-internal-real-time)))
(values result (inexact->exact (round (* 1000.0 (/ (- end start) internal-time-units-per-second)))))))
(display "\n")
(display "═══════════════════════════════════════════════════════════════════\n")
(display "GPU Benchmark (proper sensory API)\n")
(display "═══════════════════════════════════════════════════════════════════\n\n")
(define *kernel-path* "/storage/projects/code/hypercore-kb/opencog-kb/language-learning/mvp/pmfg-kernel.cl")
;; ─────────────────────────────────────────────────────────────────────
;; Test 1: OpenclNode creation + open
;; ─────────────────────────────────────────────────────────────────────
(display "TEST 1: OpenclNode creation and open\n")
(display "─────────────────────────────────────────────────────────────────────\n\n")
(define gpu-node #f)
(call-with-values
(lambda ()
(time-ms (lambda ()
(set! gpu-node (OpenclNode (string-append "opencl://:" *kernel-path*)))
(cog-execute! (SetValue gpu-node (Predicate "*-open-*") (Type 'FloatValue))))))
(lambda (result ms)
(format #t " OpenclNode creation + open: ~a ms~%" ms)))
(format #t " Node: ~a~%~%" (cog-name gpu-node))
;; ─────────────────────────────────────────────────────────────────────
;; Test 2: Kernel execution (dispatch thread fix)
;; ─────────────────────────────────────────────────────────────────────
(display "TEST 2: Kernel execution (dispatch thread fix)\n")
(display "─────────────────────────────────────────────────────────────────────\n\n")
(display " BEFORE FIX: First kernel takes 16+ seconds (OpenCL thread init)\n")
(display " AFTER FIX: First kernel should take <1 second\n\n")
;; First kernel execution
(define result1 #f)
(call-with-values
(lambda ()
(time-ms (lambda ()
(cog-execute!
(SetValue gpu-node (Predicate "*-write-*")
(Section (Item "test_simple")
(ConnectorSeq (Number 1 2 3 4) (Number 0 0 0 0)))))
(set! result1 (cog-execute! (ValueOf gpu-node (Predicate "*-read-*")))))))
(lambda (result ms)
(format #t " First kernel execution: ~a ms~%" ms)
(if (> ms 5000)
(display " ⚠ SLOW! Dispatch thread fix may not be installed.\n")
(display " ✓ Fast - dispatch thread fix is working!\n"))))
(format #t " Result (x*2+42 for 1,2,3,4): ~a~%~%" result1)
;; Second execution
(define result2 #f)
(call-with-values
(lambda ()
(time-ms (lambda ()
(cog-execute!
(SetValue gpu-node (Predicate "*-write-*")
(Section (Item "test_simple")
(ConnectorSeq (Number 10 20 30 40) (Number 0 0 0 0)))))
(set! result2 (cog-execute! (ValueOf gpu-node (Predicate "*-read-*")))))))
(lambda (result ms)
(format #t " Second kernel execution: ~a ms~%" ms)))
(format #t " Result (x*2+42 for 10,20,30,40): ~a~%~%" result2)
;; Third execution
(define result3 #f)
(call-with-values
(lambda ()
(time-ms (lambda ()
(cog-execute!
(SetValue gpu-node (Predicate "*-write-*")
(Section (Item "test_simple")
(ConnectorSeq (Number 100 200 300 400) (Number 0 0 0 0)))))
(set! result3 (cog-execute! (ValueOf gpu-node (Predicate "*-read-*")))))))
(lambda (result ms)
(format #t " Third kernel execution: ~a ms~%~%" ms)))
(format #t " Result: ~a~%~%" result3)
;; ─────────────────────────────────────────────────────────────────────
;; Test 3: Rapid execution (10 iterations)
;; ─────────────────────────────────────────────────────────────────────
(display "TEST 3: Rapid execution (10 iterations)\n")
(display "─────────────────────────────────────────────────────────────────────\n\n")
(define total-time 0)
(do ((i 0 (+ i 1)))
((= i 10))
(call-with-values
(lambda ()
(time-ms (lambda ()
(cog-execute!
(SetValue gpu-node (Predicate "*-write-*")
(Section (Item "test_simple")
(ConnectorSeq (Number i (+ i 1) (+ i 2) (+ i 3))
(Number 0 0 0 0)))))
(cog-execute! (ValueOf gpu-node (Predicate "*-read-*"))))))
(lambda (result ms)
(set! total-time (+ total-time ms))
(format #t " Iteration ~a: ~a ms~%" i ms))))
(format #t "~% Total: ~a ms, Average: ~a ms~%~%"
total-time (/ total-time 10.0))
;; ─────────────────────────────────────────────────────────────────────
;; Summary
;; ─────────────────────────────────────────────────────────────────────
(display "═══════════════════════════════════════════════════════════════════\n")
(display "SUMMARY\n")
(display "═══════════════════════════════════════════════════════════════════\n\n")
(display "Dispatch thread fix status:\n")
(display " • If first execution was <1000ms: Fix is working!\n")
(display " • If first execution was 16+ seconds: Fix NOT installed\n\n")
(display "Expected results with fixes:\n")
(display " • test_simple(1,2,3,4) = (OpenclFloatValue 44 46 48 50)\n")
(display " • test_simple(10,20,30,40) = (OpenclFloatValue 62 82 102 122)\n")
(display " • test_simple(100,200,300,400) = (OpenclFloatValue 242 442 642 842)\n\n")