bench.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. ; -*- mode: scheme; coding: utf-8 -*-
  2. ; Replacement for Guile C-based array system - Benchmarks
  3. ; (c) Daniel Llorens - 2016-2017
  4. ; This library is free software; you can redistribute it and/or modify it under
  5. ; the terms of the GNU General Public License as published by the Free
  6. ; Software Foundation; either version 3 of the License, or (at your option) any
  7. ; later version.
  8. ; Run with $GUILE -L mod -s bench.scm
  9. (import (newra newra) (newra tools) (newra test) (newra read) (ice-9 popen)
  10. (ice-9 rdelim) (srfi :26) (srfi :8) (only (srfi :1) fold iota)
  11. (ice-9 match) (ice-9 format) (only (rnrs base) vector-map))
  12. (define (command-output cmd . args)
  13. (let* ((p (apply open-pipe* OPEN_READ cmd args))
  14. (s (read-delimited "" p))
  15. (ec (status:exit-val (close-pipe p))))
  16. (values s ec)))
  17. (format #t "Guile ~a\n~!" (version))
  18. (format #t "newra ~a\n~!" (command-output "git" "describe" "--always" "--dirty"))
  19. (define (format-header . x)
  20. (apply format #t
  21. (string-append (apply string-append "~30t" (map (const "~15@a") x))
  22. "\n")
  23. x))
  24. (define (format-line . x)
  25. (apply format #t
  26. (string-append (apply string-append "~30t" (map (const "~15,3f") x))
  27. "\n")
  28. x))
  29. ; -----------------------
  30. ; benchmarks
  31. ; -----------------------
  32. (let ((m #e1e5))
  33. (format #t "\nra-cell (applicable function) / array-ref\n==================\n")
  34. (for-each
  35. (lambda (type)
  36. (format #t "\ntype ~a\n---------" type)
  37. (format-header "ra-ref" "ra-cell" "ra-appl" "array-ref")
  38. (for-each
  39. (lambda (rank)
  40. (let* ((n (inexact->exact (ceiling (expt m (/ rank)))))
  41. (nn (make-list rank n))
  42. (len (fold * 1 nn))
  43. (scale (* 1e3 (/ m len)))
  44. (ra (as-ra (make-ra-root (make-dim len) (apply c-dims nn)) #:type type))
  45. (a (ra->array ra))
  46. (ras 0)
  47. (as 0)
  48. ; FIXME test ra-ref / ra-cell / (ra ...)
  49. (raf-ref (case-lambda ((i) (set! ras (+ ras (ra-ref ra i))))
  50. ((i j) (set! ras (+ ras (ra-ref ra i j))))
  51. ((i j k) (set! ras (+ ras (ra-ref ra i j k))))
  52. ((i j k l) (set! ras (+ ras (ra-ref ra i j k l))))
  53. ((i j k l m) (set! ras (+ ras (ra-ref ra i j k l m))))))
  54. (raf-cell (case-lambda ((i) (set! ras (+ ras (ra-cell ra i))))
  55. ((i j) (set! ras (+ ras (ra-cell ra i j))))
  56. ((i j k) (set! ras (+ ras (ra-cell ra i j k))))
  57. ((i j k l) (set! ras (+ ras (ra-cell ra i j k l))))
  58. ((i j k l m) (set! ras (+ ras (ra-cell ra i j k l m))))))
  59. (raf-appl (case-lambda ((i) (set! ras (+ ras (ra i))))
  60. ((i j) (set! ras (+ ras (ra i j))))
  61. ((i j k) (set! ras (+ ras (ra i j k))))
  62. ((i j k l) (set! ras (+ ras (ra i j k l))))
  63. ((i j k l m) (set! ras (+ ras (ra i j k l m))))))
  64. (af (case-lambda ((i) (set! as (+ as (array-ref a i))))
  65. ((i j) (set! as (+ as (array-ref a i j))))
  66. ((i j k) (set! as (+ ras (array-ref a i j k))))
  67. ((i j k l) (set! as (+ ras (array-ref a i j k l))))
  68. ((i j k l m) (set! as (+ ras (array-ref a i j k l m)))))))
  69. (unless (= ras as) (throw 'error-in-ra-cell-array-ref-check))
  70. (format #t "rank ~a ~a:" rank nn)
  71. (format-line (* scale (time (ra-loop ra raf-ref)))
  72. (* scale (time (ra-loop ra raf-cell)))
  73. (* scale (time (ra-loop ra raf-appl)))
  74. (* scale (time (array-loop a af))))))
  75. (iota 5 1)))
  76. '(#t f64)))
  77. (let ((m #e1e5))
  78. (format #t "\nra-slice-for-each array-slice-for-each ra-map! array-map!\n==================\n")
  79. (for-each
  80. (lambda (type)
  81. (for-each
  82. (lambda (nargs)
  83. (format #t "\ntype ~a ~a args\n---------" type nargs)
  84. (format-header "ra*" "array*" "ra" "array")
  85. (for-each
  86. (lambda (rank)
  87. (let* ((n (inexact->exact (ceiling (expt m (/ rank)))))
  88. (nn (make-list rank n))
  89. (len (fold * 1 nn))
  90. (scale (* 1e3 (/ m len)))
  91. (ra20 (make-ra-new type *unspecified* (apply c-dims nn)))
  92. (ra21 (ra-map*! ra-slice-for-each (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  93. (ra22 (ra-map*! ra-slice-for-each (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  94. (a20 (ra->array ra20))
  95. (a21 (ra->array ra21))
  96. (a22 (ra->array ra22)))
  97. (format #t "rank ~a ~a:" rank nn)
  98. (case nargs
  99. ((3)
  100. (format-line (* scale (time (ra-map*! ra-slice-for-each-4 ra20 - ra21 ra22)))
  101. (* scale (time (array-map*! a20 - a21 a22)))
  102. (* scale (time (ra-map! ra20 - ra21 ra22)))
  103. (* scale (time (array-map! a20 - a21 a22)))))
  104. ((2)
  105. (format-line (* scale (time (ra-map*! ra-slice-for-each-4 ra20 - ra21)))
  106. (* scale (time (array-map*! a20 - a21)))
  107. (* scale (time (ra-map! ra20 - ra21)))
  108. (* scale (time (array-map! a20 - a21)))))
  109. ((1)
  110. (format-line (* scale (time (ra-map*! ra-slice-for-each-4 ra20 (lambda () (random n)))))
  111. (* scale (time (array-map*! a20 (lambda () (random n)))))
  112. (* scale (time (ra-map! ra20 (lambda () (random n)))))
  113. (* scale (time (array-map! a20 (lambda () (random n))))))))))
  114. (iota 6 1)))
  115. (iota 3 1)))
  116. '(#t f64)))
  117. (let ((m #e5e5))
  118. (format #t "\nra-copy! array-copy!\n==================\n")
  119. (for-each
  120. (lambda (typesrc typedst)
  121. (format #t "\ntype src ~a -> type dst ~a\n---------" typesrc typedst)
  122. (format-header "ra" "array")
  123. (for-each
  124. (lambda (rank)
  125. (let* ((n (inexact->exact (ceiling (expt m (/ rank)))))
  126. (nn (make-list rank n))
  127. (len (fold * 1 nn))
  128. (scale (* 1e3 (/ m len)))
  129. (ra20 (make-ra-new typesrc *unspecified* (apply c-dims nn)))
  130. (ra21 (ra-map! (make-ra-new typedst 0 (apply c-dims nn)) (lambda () (random n))))
  131. (a20 (ra->array ra20))
  132. (a21 (ra->array ra21)))
  133. (format #t "rank ~a ~a:" rank nn)
  134. (format-line (* scale (time (ra-copy! ra20 ra21)))
  135. (* scale (time (array-copy! a21 a20))))))
  136. (iota 6 1)))
  137. (list #t 'f64 #t)
  138. (list #t 'f64 'f64)))
  139. (let ((m #e5e5))
  140. (format #t "\nra-fill! array-fill!\n==================\n")
  141. (for-each
  142. (lambda (type)
  143. (format #t "\ntype dst ~a\n----------" type)
  144. (format-header "ra" "array")
  145. (for-each
  146. (lambda (rank)
  147. (let* ((n (inexact->exact (ceiling (expt m (/ rank)))))
  148. (nn (make-list rank n))
  149. (len (fold * 1 nn))
  150. (scale (* 1e3 (/ m len)))
  151. (ra20 (make-ra-new type *unspecified* (apply c-dims nn)))
  152. (a20 (ra->array ra20)))
  153. (format #t "rank ~a ~a:" rank nn)
  154. (format-line (* scale (time (ra-fill! ra20 77)))
  155. (* scale (time (array-fill! a20 77))))))
  156. (iota 6 1)))
  157. (list #t 'f64 'u8)))
  158. (let ((m #e5e5))
  159. (format #t "\nra-equal? array-equal?\n==================\n")
  160. (for-each
  161. (lambda (type)
  162. (format #t "\ntype dst ~a\n----------" type)
  163. (format-header "ra" "array")
  164. (for-each
  165. (lambda (rank)
  166. (let* ((n (inexact->exact (ceiling (expt m (/ rank)))))
  167. (nn (make-list rank n))
  168. (len (fold * 1 nn))
  169. (scale (* 1e3 (/ m len)))
  170. (ra20 (ra-map! (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  171. (ra21 (ra-copy! (make-ra-new type 0 (apply c-dims nn)) ra20))
  172. (a20 (ra->array ra20))
  173. (a21 (ra->array ra21)))
  174. (format #t "rank ~a ~a:" rank nn)
  175. (format-line (* scale (time (ra-equal? ra20 ra21)))
  176. (* scale (time (array-equal? a20 a21))))))
  177. (iota 6 1)))
  178. (list #t 'f64)))
  179. (let ((m #e1e4))
  180. (format #t "\nprinting\n==================\n")
  181. (for-each
  182. (lambda (type)
  183. (format #t "\ntype dst ~a\n----------" type)
  184. (format-header "ra" "array1" "array2")
  185. (for-each
  186. (lambda (rank)
  187. (let* ((n (inexact->exact (ceiling (expt m (/ rank)))))
  188. (nn (make-list rank n))
  189. (len (fold * 1 nn))
  190. (scale (* 1e3 (/ m len)))
  191. (ra (ra-map! (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  192. (a (ra->array ra)))
  193. (format #t "rank ~a ~a:" rank nn)
  194. (format-line (* scale (time (call-with-output-file "/dev/null" (cut display ra <>))))
  195. (* scale (time (call-with-output-file "/dev/null" (cut array-print* a <>))))
  196. (* scale (time (call-with-output-file "/dev/null" (cut display a <>)))))))
  197. (iota 6 1)))
  198. (list #t 'f64)))
  199. (let ((m #e1e4))
  200. (format #t "\nreading\n==================\n")
  201. (for-each
  202. (lambda (type)
  203. (format #t "\ntype dst ~a\n----------" type)
  204. (format-header "ra1" "ra2" "array")
  205. (for-each
  206. (lambda (rank)
  207. (let* ((n (inexact->exact (ceiling (expt m (/ rank)))))
  208. (nn (make-list rank n))
  209. (len (fold * 1 nn))
  210. (scale (* 1e3 (/ m len)))
  211. (ra (ra-map! (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  212. (sra1 (call-with-output-string (cut (@@ (newra print) ra-print) ra <> #:dims? #t)))
  213. (sra2 (call-with-output-string (cut (@@ (newra print) ra-print) ra <> #:dims? #f)))
  214. (a (ra->array ra))
  215. (sa (call-with-output-string (cut display a <>))))
  216. (format #t "rank ~a ~a:" rank nn)
  217. (let ((rb #f) (b #f))
  218. (format-line (* scale (time (set! rb (call-with-input-string sra1 read))))
  219. (* scale (time (set! rb (call-with-input-string sra2 read))))
  220. (* scale (time (set! b (call-with-input-string sa read)))))
  221. (unless (array-equal? (ra->array rb) b) (throw 'bad-reading-benchmark)))))
  222. (iota 6 1)))
  223. (list #t 'f64)))
  224. (let ((m #e1e5))
  225. (format #t "\nlist->ra\n==================\n")
  226. (for-each
  227. (lambda (type)
  228. (format #t "\ntype dst ~a\n----------" type)
  229. (format-header "ra" "array" "ra/shape" "array/shape")
  230. (for-each
  231. (lambda (rank)
  232. (let* ((n (inexact->exact (ceiling (expt m (/ rank)))))
  233. (nn (make-list rank n))
  234. (len (fold * 1 nn))
  235. (scale (* 1e3 (/ m len)))
  236. (ra (ra-map! (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  237. (la (ra->list ra))
  238. (shape (map (lambda (len) (list 0 (- len 1))) nn)))
  239. (format #t "rank ~a ~a:" rank nn)
  240. (let ((rb #f) (b #f))
  241. (format-line (* scale (time (set! rb (list->ra rank la))))
  242. (* scale (time (set! b (list->array rank la))))
  243. (* scale (time (set! rb (list->typed-ra type shape la))))
  244. (* scale (time (set! b (list->typed-array type shape la)))))
  245. (unless (array-equal? (ra->array ra) b) (throw 'bad-ra->list-benchmark))
  246. (unless (array-equal? (ra->array rb) b) (throw 'bad-ra->list-benchmark)))))
  247. (iota 6 1)))
  248. (list #t 'f64)))
  249. (let ((m #e1e5))
  250. (format #t "\nra->list\n==================\n")
  251. (for-each
  252. (lambda (type)
  253. (format #t "\ntype dst ~a\n----------" type)
  254. (format-header "ra" "array")
  255. (for-each
  256. (lambda (rank)
  257. (let* ((n (inexact->exact (ceiling (expt m (/ rank)))))
  258. (nn (make-list rank n))
  259. (len (fold * 1 nn))
  260. (scale (* 1e3 (/ m len)))
  261. (ra (ra-map! (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  262. (array (ra->array ra))
  263. (la (ra->list ra))
  264. (shape (map (lambda (len) (list 0 (- len 1))) nn)))
  265. (format #t "rank ~a ~a:" rank nn)
  266. (let ((lb #f) (b #f))
  267. (format-line (* scale (time (set! lb (ra->list ra))))
  268. (* scale (time (set! b (array->list array)))))
  269. (unless (equal? la b) (throw 'bad-ra->list-benchmark))
  270. (unless (equal? lb b) (throw 'bad-ra->list-benchmark)))))
  271. (iota 6 1)))
  272. (list #t 'f64)))
  273. ; -----------------------
  274. ; ra-index-map!
  275. ; -----------------------
  276. (let ((m #e1e5))
  277. (format #t "\nra-index-map!\n==================\n")
  278. (for-each
  279. (lambda (type)
  280. (format #t "\ntype dst ~a\n----------" type)
  281. (format-header "ra" "array")
  282. (for-each
  283. (lambda (rank)
  284. (let* ((op (lambda x (apply + x)))
  285. (n (inexact->exact (ceiling (expt m (/ rank)))))
  286. (nn (make-list rank n))
  287. (len (fold * 1 nn))
  288. (scale (* 1e3 (/ m len)))
  289. (ra (ra-map! (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  290. (array (ra->array ra)))
  291. (format #t "rank ~a ~a:" rank nn)
  292. (format-line (* scale (time (ra-index-map! ra op)))
  293. (* scale (time (array-index-map! array op))))
  294. (unless (array-equal? (ra->array ra) array) (throw 'bad-ra-index-map!-benchmark))))
  295. (iota 3 1)))
  296. (list #t 'f64)))
  297. ; -----------------------
  298. ; some profiling...
  299. ; -----------------------
  300. (import (statprof))
  301. (format #t "\nstatprof...\n==================\n")
  302. (let* ((m #e5e4)
  303. (type #t)
  304. (rank 3)
  305. (n (inexact->exact (ceiling (expt (* 10 m) (/ rank)))))
  306. (nn (make-list rank n))
  307. (ra0 (make-ra-new type *unspecified* (apply c-dims nn)))
  308. (ra1 (ra-map! (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  309. (ra2 (ra-map! (make-ra-new type 0 (apply c-dims nn)) (lambda () (random n))))
  310. (s (call-with-output-string (cut display ra1 <>)))
  311. (prof (lambda () (call-with-input-string s read)))
  312. (prof (lambda () (ra-fill! ra0 99)))
  313. (prof (lambda () (ra-copy! ra2 ra1)))
  314. (prof (lambda () (ra-map! ra0 * ra1 ra2)))
  315. )
  316. (statprof prof #:count-calls? #t)
  317. prof)