Advertisement
SkyCrafter0

scimark.lua

Nov 12th, 2020 (edited)
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.08 KB | None | 0 0
  1. ------------------------------------------------------------------------------
  2. -- Lua SciMark (2010-12-20).
  3. --
  4. -- A literal translation of SciMark 2.0a, written in Java and C.
  5. -- Credits go to the original authors Roldan Pozo and Bruce Miller.
  6. -- See: http://math.nist.gov/scimark2/
  7. ------------------------------------------------------------------------------
  8. -- Copyright (C) 2006-2010 Mike Pall. All rights reserved.
  9. --
  10. -- Permission is hereby granted, free of charge, to any person obtaining
  11. -- a copy of this software and associated documentation files (the
  12. -- "Software"), to deal in the Software without restriction, including
  13. -- without limitation the rights to use, copy, modify, merge, publish,
  14. -- distribute, sublicense, and/or sell copies of the Software, and to
  15. -- permit persons to whom the Software is furnished to do so, subject to
  16. -- the following conditions:
  17. --
  18. -- The above copyright notice and this permission notice shall be
  19. -- included in all copies or substantial portions of the Software.
  20. --
  21. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. -- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  24. -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  25. -- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  26. -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  27. -- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. --
  29. -- [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
  30. ------------------------------------------------------------------------------
  31.  
  32. local SCIMARK_VERSION = "2010-12-10"
  33. local SCIMARK_COPYRIGHT = "Copyright (C) 2006-2010 Mike Pall"
  34.  
  35. local MIN_TIME = 2.0
  36. local RANDOM_SEED = 101009 -- Must be odd.
  37. local SIZE_SELECT = "small"
  38.  
  39. local benchmarks = {
  40. "FFT", "SOR", "MC", "SPARSE", "LU",
  41. small = {
  42. FFT = { 1024 },
  43. SOR = { 100 },
  44. MC = { },
  45. SPARSE = { 1000, 5000 },
  46. LU = { 100 },
  47. },
  48. large = {
  49. FFT = { 1048576 },
  50. SOR = { 1000 },
  51. MC = { },
  52. SPARSE = { 100000, 1000000 },
  53. LU = { 1000 },
  54. },
  55. }
  56.  
  57. local abs, log, sin, floor = math.abs, math.log, math.sin, math.floor
  58. local pi, clock = math.pi, os.clock
  59. local format = string.format
  60.  
  61. ------------------------------------------------------------------------------
  62. -- Select array type: Lua tables or native (FFI) arrays
  63. ------------------------------------------------------------------------------
  64.  
  65. local darray, iarray
  66.  
  67. local function array_init()
  68. if jit and jit.status and jit.status() then
  69. local ok, ffi = pcall(require, "ffi")
  70. if ok then
  71. darray = ffi.typeof("double[?]")
  72. iarray = ffi.typeof("int[?]")
  73. return
  74. end
  75. end
  76. function darray(n) return {} end
  77. iarray = darray
  78. end
  79.  
  80. ------------------------------------------------------------------------------
  81. -- This is a Lagged Fibonacci Pseudo-random Number Generator with
  82. -- j, k, M = 5, 17, 31. Pretty weak, but same as C/Java SciMark.
  83. ------------------------------------------------------------------------------
  84.  
  85. local rand, rand_init
  86.  
  87. if jit and jit.status and jit.status() then
  88. -- LJ2 has bit operations and zero-based arrays (internally).
  89. local bit = bit or require("bit")
  90. local band, sar = bit.band, bit.arshift
  91. function rand_init(seed)
  92. local Rm, Rj, Ri = iarray(17), 16, 11
  93. for i=0,16 do Rm[i] = 0 end
  94. for i=16,0,-1 do
  95. seed = band(seed*9069, 0x7fffffff)
  96. Rm[i] = seed
  97. end
  98. function rand()
  99. local i = band(Ri+1, sar(Ri-16, 31))
  100. local j = band(Rj+1, sar(Rj-16, 31))
  101. Ri, Rj = i, j
  102. local k = band(Rm[i] - Rm[j], 0x7fffffff)
  103. Rm[j] = k
  104. return k * (1.0/2147483647.0)
  105. end
  106. end
  107. else
  108. -- Better for standard Lua with one-based arrays and without bit operations.
  109. function rand_init(seed)
  110. local Rm, Rj = {}, 1
  111. for i=1,17 do Rm[i] = 0 end
  112. for i=17,1,-1 do
  113. seed = (seed*9069) % (2^31)
  114. Rm[i] = seed
  115. end
  116. function rand()
  117. local j, m = Rj, Rm
  118. local h = j - 5
  119. if h < 1 then h = h + 17 end
  120. local k = m[h] - m[j]
  121. if k < 0 then k = k + 2147483647 end
  122. m[j] = k
  123. if j < 17 then Rj = j + 1 else Rj = 1 end
  124. return k * (1.0/2147483647.0)
  125. end
  126. end
  127. end
  128.  
  129. local function random_vector(n)
  130. local v = darray(n+1)
  131. for x=1,n do v[x] = rand() end
  132. return v
  133. end
  134.  
  135. local function random_matrix(m, n)
  136. local a = {}
  137. for y=1,m do
  138. local v = darray(n+1)
  139. a[y] = v
  140. for x=1,n do v[x] = rand() end
  141. end
  142. return a
  143. end
  144.  
  145. ------------------------------------------------------------------------------
  146. -- FFT: Fast Fourier Transform.
  147. ------------------------------------------------------------------------------
  148.  
  149. local function fft_bitreverse(v, n)
  150. local j = 0
  151. for i=0,2*n-4,2 do
  152. if i < j then
  153. v[i+1], v[i+2], v[j+1], v[j+2] = v[j+1], v[j+2], v[i+1], v[i+2]
  154. end
  155. local k = n
  156. while k <= j do j = j - k; k = k / 2 end
  157. j = j + k
  158. end
  159. end
  160.  
  161. local function fft_transform(v, n, dir)
  162. if n <= 1 then return end
  163. fft_bitreverse(v, n)
  164. local dual = 1
  165. repeat
  166. local dual2 = 2*dual
  167. for i=1,2*n-1,2*dual2 do
  168. local j = i+dual2
  169. local ir, ii = v[i], v[i+1]
  170. local jr, ji = v[j], v[j+1]
  171. v[j], v[j+1] = ir - jr, ii - ji
  172. v[i], v[i+1] = ir + jr, ii + ji
  173. end
  174. local theta = dir * pi / dual
  175. local s, s2 = sin(theta), 2.0 * sin(theta * 0.5)^2
  176. local wr, wi = 1.0, 0.0
  177. for a=3,dual2-1,2 do
  178. wr, wi = wr - s*wi - s2*wr, wi + s*wr - s2*wi
  179. for i=a,a+2*(n-dual2),2*dual2 do
  180. local j = i+dual2
  181. local jr, ji = v[j], v[j+1]
  182. local dr, di = wr*jr - wi*ji, wr*ji + wi*jr
  183. local ir, ii = v[i], v[i+1]
  184. v[j], v[j+1] = ir - dr, ii - di
  185. v[i], v[i+1] = ir + dr, ii + di
  186. end
  187. end
  188. dual = dual2
  189. until dual >= n
  190. end
  191.  
  192. function benchmarks.FFT(n)
  193. local l2n = log(n)/log(2)
  194. if l2n % 1 ~= 0 then
  195. io.stderr:write("Error: FFT data length is not a power of 2\n")
  196. os.exit(1)
  197. end
  198. local v = random_vector(n*2)
  199. return function(cycles)
  200. local norm = 1.0 / n
  201. for p=1,cycles do
  202. fft_transform(v, n, -1)
  203. fft_transform(v, n, 1)
  204. for i=1,n*2 do v[i] = v[i] * norm end
  205. end
  206. return ((5*n-2)*l2n + 2*(n+1)) * cycles
  207. end
  208. end
  209.  
  210. ------------------------------------------------------------------------------
  211. -- SOR: Jacobi Successive Over-Relaxation.
  212. ------------------------------------------------------------------------------
  213.  
  214. local function sor_run(mat, m, n, cycles, omega)
  215. local om4, om1 = omega*0.25, 1.0-omega
  216. m = m - 1
  217. n = n - 1
  218. for i=1,cycles do
  219. for y=2,m do
  220. local v, vp, vn = mat[y], mat[y-1], mat[y+1]
  221. for x=2,n do
  222. v[x] = om4*((vp[x]+vn[x])+(v[x-1]+v[x+1])) + om1*v[x]
  223. end
  224. end
  225. end
  226. end
  227.  
  228. function benchmarks.SOR(n)
  229. local mat = random_matrix(n, n)
  230. return function(cycles)
  231. sor_run(mat, n, n, cycles, 1.25)
  232. return (n-1)*(n-1)*cycles*6
  233. end
  234. end
  235.  
  236. ------------------------------------------------------------------------------
  237. -- MC: Monte Carlo Integration.
  238. ------------------------------------------------------------------------------
  239.  
  240. local function mc_integrate(cycles)
  241. local under_curve = 0
  242. local rand = rand
  243. for i=1,cycles do
  244. local x = rand()
  245. local y = rand()
  246. if x*x + y*y <= 1.0 then under_curve = under_curve + 1 end
  247. end
  248. return (under_curve/cycles) * 4
  249. end
  250.  
  251. function benchmarks.MC()
  252. return function(cycles)
  253. local res = mc_integrate(cycles)
  254. assert(math.sqrt(cycles)*math.abs(res-math.pi) < 5.0, "bad MC result")
  255. return cycles * 4 -- Way off, but same as SciMark in C/Java.
  256. end
  257. end
  258.  
  259. ------------------------------------------------------------------------------
  260. -- Sparse Matrix Multiplication.
  261. ------------------------------------------------------------------------------
  262.  
  263. local function sparse_mult(n, cycles, vy, val, row, col, vx)
  264. for p=1,cycles do
  265. for r=1,n do
  266. local sum = 0
  267. for i=row[r],row[r+1]-1 do sum = sum + vx[col[i]] * val[i] end
  268. vy[r] = sum
  269. end
  270. end
  271. end
  272.  
  273. function benchmarks.SPARSE(n, nz)
  274. local nr = floor(nz/n)
  275. local anz = nr*n
  276. local vx = random_vector(n)
  277. local val = random_vector(anz)
  278. local vy, col, row = darray(n+1), iarray(nz+1), iarray(n+2)
  279. row[1] = 1
  280. for r=1,n do
  281. local step = floor(r/nr)
  282. if step < 1 then step = 1 end
  283. local rr = row[r]
  284. row[r+1] = rr+nr
  285. for i=0,nr-1 do col[rr+i] = 1+i*step end
  286. end
  287. return function(cycles)
  288. sparse_mult(n, cycles, vy, val, row, col, vx)
  289. return anz*cycles*2
  290. end
  291. end
  292.  
  293. ------------------------------------------------------------------------------
  294. -- LU: Dense Matrix Factorization.
  295. ------------------------------------------------------------------------------
  296.  
  297. local function lu_factor(a, pivot, m, n)
  298. local min_m_n = m < n and m or n
  299. for j=1,min_m_n do
  300. local jp, t = j, abs(a[j][j])
  301. for i=j+1,m do
  302. local ab = abs(a[i][j])
  303. if ab > t then
  304. jp = i
  305. t = ab
  306. end
  307. end
  308. pivot[j] = jp
  309. if a[jp][j] == 0 then error("zero pivot") end
  310. if jp ~= j then a[j], a[jp] = a[jp], a[j] end
  311. if j < m then
  312. local recp = 1.0 / a[j][j]
  313. for k=j+1,m do
  314. local v = a[k]
  315. v[j] = v[j] * recp
  316. end
  317. end
  318. if j < min_m_n then
  319. for i=j+1,m do
  320. local vi, vj = a[i], a[j]
  321. local eij = vi[j]
  322. for k=j+1,n do vi[k] = vi[k] - eij * vj[k] end
  323. end
  324. end
  325. end
  326. end
  327.  
  328. local function matrix_alloc(m, n)
  329. local a = {}
  330. for y=1,m do a[y] = darray(n+1) end
  331. return a
  332. end
  333.  
  334. local function matrix_copy(dst, src, m, n)
  335. for y=1,m do
  336. local vd, vs = dst[y], src[y]
  337. for x=1,n do vd[x] = vs[x] end
  338. end
  339. end
  340.  
  341. function benchmarks.LU(n)
  342. local mat = random_matrix(n, n)
  343. local tmp = matrix_alloc(n, n)
  344. local pivot = iarray(n+1)
  345. return function(cycles)
  346. for i=1,cycles do
  347. matrix_copy(tmp, mat, n, n)
  348. lu_factor(tmp, pivot, n, n)
  349. end
  350. return 2.0/3.0*n*n*n*cycles
  351. end
  352. end
  353.  
  354. ------------------------------------------------------------------------------
  355. -- Main program.
  356. ------------------------------------------------------------------------------
  357.  
  358. local function printf(...)
  359. io.write(format(...))
  360. end
  361.  
  362. local function fmtparams(p1, p2)
  363. if p2 then return format("[%d, %d]", p1, p2)
  364. elseif p1 then return format("[%d]", p1) end
  365. return ""
  366. end
  367.  
  368. local function measure(min_time, name, ...)
  369. array_init()
  370. rand_init(RANDOM_SEED)
  371. local run = benchmarks[name](...)
  372. local cycles = 1
  373. repeat
  374. local tm = clock()
  375. local flops = run(cycles, ...)
  376. tm = clock() - tm
  377. if tm >= min_time then
  378. local res = flops / tm * 1.0e-6
  379. local p1, p2 = ...
  380. printf("%-7s %8.2f %s\n", name, res, fmtparams(...))
  381. return res
  382. end
  383. cycles = cycles * 2
  384. until false
  385. end
  386.  
  387. local unpack = table.unpack or unpack
  388.  
  389. printf("Lua SciMark %s based on SciMark 2.0a. %s.\n\n",
  390. SCIMARK_VERSION, SCIMARK_COPYRIGHT)
  391.  
  392. while arg and arg[1] do
  393. local a = table.remove(arg, 1)
  394. if a == "-noffi" then
  395. package.preload.ffi = nil
  396. elseif a == "-small" then
  397. SIZE_SELECT = "small"
  398. elseif a == "-large" then
  399. SIZE_SELECT = "large"
  400. elseif benchmarks[a] then
  401. local p = benchmarks[SIZE_SELECT][a]
  402. measure(MIN_TIME, a, tonumber(arg[1]) or p[1], tonumber(arg[2]) or p[2])
  403. return
  404. else
  405. printf("Usage: scimark [-noffi] [-small|-large] [BENCH params...]\n\n")
  406. printf("BENCH -small -large\n")
  407. printf("---------------------------------------\n")
  408. for _,name in ipairs(benchmarks) do
  409. printf("%-7s %-13s %s\n", name,
  410. fmtparams(unpack(benchmarks.small[name])),
  411. fmtparams(unpack(benchmarks.large[name])))
  412. end
  413. printf("\n")
  414. os.exit(1)
  415. end
  416. end
  417.  
  418. local params = benchmarks[SIZE_SELECT]
  419. local sum = 0
  420. for _,name in ipairs(benchmarks) do
  421. sum = sum + measure(MIN_TIME, name, unpack(params[name]))
  422. os.queueEvent("nosleep")
  423. os.pullEvent()
  424. end
  425. printf("\nSciMark %8.2f [%s problem sizes]\n", sum / #benchmarks, SIZE_SELECT)
  426. io.flush()
  427.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement