OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomese-simd / tests / opencl / opencl-vec-test.scm

197 lines · scm ref:
;
; opencl-vec-test.scm
;
; Basic OpenCL vector multiplication unit test.
;
(use-modules (srfi srfi-1))
(use-modules (opencog) (opencog exec))
(use-modules (opencog sensory) (opencog opencl))
(use-modules (opencog test-runner))

; (define clurl "opencl://Clover:AMD Radeon/tmp/vec-kernel.cl")
; (define clurl "opencl://CUDA:NVIDIA RTX 4000/tmp/vec-kernel.cl")

; Horrible hackery to extract location of the unit test.
; Currently works only with absolute paths; relative paths ar broken.
(format #t "Command line: ~A\n" (command-line))
(define last-arg (last (command-line)))
(define pathcomp (string-split last-arg #\/))
(define leader (take pathcomp (- (length pathcomp) 1)))

; leading char of path should be either slash, or dot.
; We want this to rebuild a relative path...
(define leading-char (list->string (list (string-ref last-arg 0))))
(define path (fold
	(lambda (s t) (string-concatenate (list t "/" s)))
	"" leader))
(format #t "Unit test location: ~A\n" path)

; If unit test is run from cmake, then pathcomp is a long list.
; Otherwise unit test is run by hand, and its just cwd.
(define curloc (if (< 1 (length pathcomp)) path (getcwd)))

(define clurl (string-concatenate (list
	"opencl://:" curloc "/vec-kernel.cl")))

(format #t "Looking for kernel at ~A\n" clurl)

(opencog-test-runner)
(define tname "opencl-vec-test")
(test-begin tname)

; ---------------------------------------------------------------

(define clnode (OpenclNode clurl))
(format #t "testing ~A" clnode)
(cog-execute!
   (SetValue clnode (Predicate "*-open-*") (Type 'FloatValue)))

; Test to see if stream is open.
(define cnct (cog-execute! (ValueOf clnode (Predicate "*-connected?-*"))))
(format #t "connected? ~A" cnct)
(test-assert "open stream" (cog-value-ref cnct 0))

; ---------------------------------------------------------------
(define kernel-runner
	(SetValue clnode (Predicate "*-write-*")
		(Section
			(Item "vec_mult")
			(ConnectorSeq
				(Number 0 0 0 0 0)
				(Number 1 2 3 4 5)
				(Number 2 2 2 2 2 2 3 42 999)))))

(cog-execute! kernel-runner)
(define kern-m1
	(cog-execute! (ValueOf clnode (Predicate "*-read-*"))))
(define args-m1 (cog-value-ref kern-m1 1))
(define out-m1 (cog-value-ref args-m1 0))
; Force out-m1 OpenclFloatValue to download from GPU by printing!!!
(format #t "Result out-m1=~A" out-m1)
(test-assert "mult one" (equal? (FloatValue 2 4 6 8 10) out-m1))

; ---------------------------------------------------------------
; Run it again, different data
(define krun-2
	(SetValue clnode (Predicate "*-write-*")
		(Section
			(Item "vec_mult")
			(ConnectorSeq
				(Number 0 0 0 0 0 0 0 0 0 0 0)
				(Number 1 2 3 4 5 6 7 8 9 10 11)
				(Number 2 3 4 5 6 5 4 3 2 1 0)))))

(cog-execute! krun-2)
(define kern-m3
	(cog-execute! (ValueOf clnode (Predicate "*-read-*"))))
(define args-m3 (cog-value-ref kern-m3 1))
(define out-m3 (cog-value-ref args-m3 0))
; Force out-m3 OpenclFloatValue to download from GPU by printing!!!
(format #t "Result out-m3=~A" out-m3)
(test-assert "mult three"
	(equal? (FloatValue 2 6 12 20 30 30 28 24 18 10 0) out-m3))

; ---------------------------------------------------------------
; Run it again, with a different kernel
(define krun-3
	(SetValue clnode (Predicate "*-write-*")
		(Section
			(Item "vec_add")
			(ConnectorSeq
				(Number 0 0 0 0 0 0 0 0 0 0 0)
				(Number 1 2 3 4 5 6 7 8 9 10 11)
				(Number 2 3 4 5 6 5 4 3 2 1 0)))))

(cog-execute! krun-3)
(define kern-m5
	(cog-execute! (ValueOf clnode (Predicate "*-read-*"))))
(define args-m5 (cog-value-ref kern-m5 1))
(define out-m5 (cog-value-ref args-m5 0))
; Force out-m5 OpenclFloatValue to download from GPU by printing!!!
(format #t "Result out-m5=~A" out-m5)
(test-assert "mult five"
	(equal? (FloatValue 3 5 7 9 11 11 11 11 11 11 11) out-m5))

; ---------------------------------------------------------------
; Initialize the accumulator
(define vec-size 130)

(cog-set-value!
	(Anchor "some place") (Predicate "accumulator")
	(OpenclFloatValue (make-list vec-size 0)))

(define accum-location
	(ValueOf (Anchor "some place") (Predicate "accumulator")))

; Upload the accumulator to the GPU.
(cog-set-value! clnode (Predicate "*-write-*") accum-location)
(cog-execute! (ValueOf clnode (Predicate "*-read-*")))

; ---------------------------------------------------------------
; Set the data source.
(cog-set-value!
	(Anchor "some place") (Predicate "data source")
	(RandomStream vec-size))

(define source-location
	(ValueOf (Anchor "some place") (Predicate "data source")))

; Define a feedback loop.
(define run-kernel
	(SetValue clnode (Predicate "*-write-*")
	(Section
		(Item "vec_add")
		(ConnectorSeq accum-location
			accum-location source-location))))

(define get-status
	(ValueOf clnode (Predicate "*-read-*")))

; Run it once ...
(cog-execute! run-kernel)
(define acc1 (cog-execute! get-status))
(test-assert "acc1 type" (cog-subtype? 'SectionValue (cog-type acc1)))
(define args1 (cog-value-ref acc1 1))
(test-assert "args1 type" (cog-subtype? 'LinkValue (cog-type args1)))
(define out1 (cog-value-ref args1 0))
(test-assert "out1 type" (cog-subtype? 'FloatValue (cog-type out1)))
(test-assert "out1 size" (equal? vec-size (length (cog-value->list out1))))
(flush-all-ports)

; Run it lots ...
(define (loopy N)
   (cog-execute! run-kernel)
   (cog-execute! get-status)
   (if (< 0 N) (loopy (- N 1))))

(define run-len 5123)
(loopy run-len)

(cog-execute! run-kernel)
(define accn (cog-execute!  get-status))
(test-assert "accn type" (cog-subtype? 'SectionValue (cog-type accn)))
(define argsn (cog-value-ref accn 1))
(test-assert "argsn type" (cog-subtype? 'LinkValue (cog-type argsn)))
(define outn (cog-value-ref argsn 0))
(test-assert "outn type" (cog-subtype? 'FloatValue (cog-type outn)))
(test-assert "outn size" (equal? vec-size (length (cog-value->list outn))))

; Result of repeated executation should be a large number,
; approx equal to 0.5 of vec-size * run-len by the central limit theorem
; and with stddev of sqrt of num samples.
(define vsum (fold + 0 (cog-value->list outn)))
(define vlen (* vec-size run-len))
(define vmean (/ vsum vlen))
(define vsigma (/ 1 (sqrt vlen)))

(format #t "sum: ~A len: ~A mean: ~A sigma: ~A\n" vsum vlen vmean vsigma)

; Acceptable deviation
(define accdev (* 5 vsigma))

(test-assert "accn lo bound" (< (- 0.5 accdev) vmean))
(test-assert "accn hi bound" (> (+ 0.5 accdev) vmean))

(test-end tname)
(opencog-test-end)