# Maple version of SciGMark # specialized version # author Laurentiu Dragan Constants := module () # {{{ export RESOLUTION_DEFAULT, RANDOM_SEED, FFT_SIZE, SOR_SIZE, SPARSE_SIZE_M, SPARSE_SIZE_nz, LU_SIZE, POLY_SIZE; RESOLUTION_DEFAULT := 2.0; RANDOM_SEED := 101010; FFT_SIZE := 4096; SOR_SIZE := 400; SPARSE_SIZE_M := 4000; SPARSE_SIZE_nz := 20000; LU_SIZE := 400; POLY_SIZE := 160; end module: # }}} Stopwatch := proc() # {{{ local m; m := module() export init, strt, stp, rd; local reset, seconds, running, total, last_time; seconds := proc() return time(); end proc; reset := proc() running := false; last_time := 0.0; total := 0.0; end proc; init := proc() reset(); end proc; strt := proc() if not running then running := true; total := 0.0; last_time := seconds(); end if; end proc; stp := proc() if running then total := total + seconds() - last_time; running := false; end if; return total; end proc; rd := proc() if running then total := total + seconds() - last_time; last_time := seconds(); end if; return total; end proc; end module: m:-init(); return m; end proc: # }}} Random := proc(seed) # {{{ local m; m := module() export init, nextDouble; local dm1, haveRange, seed, initialize, m, i, j, m1, m2, mdig; mdig := 32; m1 := (2^(mdig - 2)) + ((2^(mdig - 2)) - 1); m2 := 2^iquo(mdig, 2); dm1 := 1.0 / m1; haveRange := false; initialize := proc(s) local jseed,k0, k1, j0, j1, iloop; seed := s; m := array(0..16); jseed := min(abs(seed), m1); if irem(jseed, 2) = 0 then jseed := jseed - 1; end if; k0 := irem(9069, m2); k1 := iquo(9069, m2); j0 := irem(jseed, m2); j1 := iquo(jseed, m2); for iloop from 0 to 16 do jseed := j0 * k0; j1 := irem(iquo(jseed,m2) + j0*k1 + j1*k0, iquo(m2,2)); j0 := irem(jseed, m2); m[iloop] := j0 + m2 * j1; end do; i := 4; j := 16; end proc; nextDouble := proc() local k, nextValue; k := m[i] - m[j]; if k < 0 then k := k + m1; end if; m[j] := k; if i = 0 then i := 16; else i := i - 1; end if; if j = 0 then j := 16; else j := j - 1; end if; if haveRange then return left + dm1 * k * width; else return dm1 * k; end if; end proc; init := proc(seed) initialize(seed); end proc: end module: m:-init(seed); return m; end proc: #}}} smFFT := proc() # {{{ local m; m := module() export num_flops, transform, inverse, test; local makeRandom, log2, transform_internal, bitreverse; num_flops := (N) -> (5.0 * N - 2) * log2(N) + 2 * (N + 1); transform := proc(data::array) transform_internal(data, -1); end proc; inverse := proc(data::array) local nd, n, norm, i; transform_internal(data, +1); nd := op(2, eval(data)); nd := op(2, nd) - op(1, nd) + 1; n := nd / 2; norm := 1 / n; for i from 0 to nd - 1 do data[i] := data[i] * norm; end do; #for i from 0 to nd - 1 do print(data[i]); end do; end proc; test := proc(data::array) local nd, cpy, diff, d, i; nd := op(2, eval(data)); nd := op(2, nd) - op(1, nd) + 1; # cpy := array(nd); cpy := copy(data); transform(data); inverse(data); diff := 0.0; for i from 0 to nd - 1 do d := data[i] - cpy[i]; diff := diff + d * d; end do; return sqrt(diff / nd); end proc; makeRandom := proc(n::integer) local nd, data, i, r; nd := 2 * n; data = array(0..nd-1); r := Random(11); for i from 0 to nd - 1 do data[i] := r:-nextDouble(); end do; return data; end proc; log2 := proc(n::integer) local l; l := log[2](n); if l <> floor(l) then print("FFT: Data length is not a power of 2!: ", n); end if; return l; end proc; transform_internal := proc(data::array, direction::integer) local n, logn, dual, bit, w_real, w_imag, theta, s, t, s2, b, i, j, wd_real, wd_imag, a, tmp_real, tmp_imag, z1_real, z1_imag; n := op(2, eval(data)); n := op(2, n) - op(1, n) + 1; # number of elements if n = 0 then return; end if; n := n/2; if n = 1 then return; end if; logn := log2(n); bitreverse(data); dual := 1; for bit from 0 to logn - 1 do w_real := 1.0; w_imag := 0.0; theta := evalhf(2.0 * direction * Pi / (2.0 * dual)); s := sin(theta); t := sin(theta / 2.0); s2 := 2.0 * t * t; for b from 0 by 2 * dual to n-1 do i := 2 * b ; j := 2 * (b + dual); wd_real := data[j] ; wd_imag := data[j+1] ; data[j] := data[i] - wd_real; data[j+1] := data[i+1] - wd_imag; data[i] := data[i] + wd_real; data[i+1] := data[i+1] + wd_imag; end do; for a from 1 to dual - 1 do tmp_real := w_real - s * w_imag - s2 * w_real; tmp_imag := w_imag + s * w_real - s2 * w_imag; w_real := tmp_real; w_imag := tmp_imag; for b from 0 by 2*dual to n - 1 do i := 2*(b + a); j := 2*(b + a + dual); z1_real := data[j]; z1_imag := data[j+1]; wd_real := w_real * z1_real - w_imag * z1_imag; wd_imag := w_real * z1_imag + w_imag * z1_real; data[j] := data[i] - wd_real; data[j+1] := data[i+1] - wd_imag; data[i] := data[i] + wd_real; data[i+1] := data[i+1] + wd_imag; end do; end do; dual := dual *2; end do; end proc; bitreverse := proc(data::array) local n, i, j, ii, jj, k, tmp_real, tmp_imag; n := op(2, eval(data)); n := (op(2, n) - op(1, n) + 1)/2; i := 0; j := 0; for i from 0 to n-2 do ii := 2*i; jj := 2*j; k := n / 2 ; if i < j then tmp_real := data[ii]; tmp_imag := data[ii+1]; data[ii] := data[jj]; data[ii+1] := data[jj+1]; data[jj] := tmp_real; data[jj+1] := tmp_imag; end if; while k <= j do j := j - k ; k := k / 2 ; end do; j := j + k; end do; end proc; end module: return m; end proc: # }}} MonteCarlo := module () #{{{ export num_flops, integrate; local SEED; SEED := 113; num_flops := proc(Num_samples) return (Num_samples)* 4.0; end proc; integrate := proc (Num_samples) local R, under_curve, count, x, y, nsm1; R := Random(SEED); under_curve := 0; nsm1 := Num_samples - 1; for count from 0 to nsm1 do x := R:-nextDouble(); y := R:-nextDouble(); if x*x + y*y <= 1.0 then under_curve := under_curve + 1; end if; end do; return (under_curve / Num_samples) * 4.0; end proc; end module: # }}} SOR := proc() # {{{ local m; m := module() export num_flops, execute; num_flops := (M,N,num_iterations) -> (M-1)*(N-1)*num_iterations*6.0; execute := proc(omega::float, G::array, num_iterations::integer) local M, N, omega_over_four, one_minus_omega, Mm1, Nm1, p, i, j, Gi, Gim1, Gip1; M := op(2, eval(G)); N := op(2, eval(G[op(1, M)])); omega_over_four := omega * 0.25; one_minus_omega := 1.0 - omega; Mm1 := op(2, M) - 1; Nm1 := op(2, N) - 1; for p from 1 to num_iterations do for i from op(1, M) + 1 to Mm1 do Gi := G[i]; Gim1 := G[i - 1]; Gip1 := G[i + 1]; for j from op(1, N)+1 to Nm1 do G[i][j] := omega_over_four * (Gim1[j] + Gip1[j] + Gi[j - 1] + Gi[j + 1]) + one_minus_omega * Gi[j]; end do: end do: end do: end proc: end module: return m; end proc: # }}} SparseCompRow := proc() # {{{ local m; m := module() export num_flops, matmult; num_flops := (N,nz,num_iterations) -> iquo(nz,N)*N*2.0*num_iterations; matmult := proc( y::array, val::array, row::array, col::array, x::array, NUM_ITERATIONS::float) local M, reps, r, s, rowR, rowRp1, i; M := op(2, eval(row)); for reps from 1 to NUM_ITERATIONS do for r from op(1, M) to op(2, M) - 1 do s := 0.0; rowR := floor(row[r]); rowRp1 := floor(row[r + 1]); for i from rowR to rowRp1 - 1 do s := s + x[floor(col[i])]*val[i]; end do: y[r] := s; end do: end do: end proc: end module: return m; end proc: # }}} LU := proc() # {{{ local m; m := module() export num_flops, solve, factor; num_flops := (N) -> 2.0 * N ^ 3 / 3.0; factor := proc(A::array, pivot::array) local N, M, minMN, j, jp, t, i, ab, tA, recp, k, ii, Aj, AiiJ, jj, Aii; N := op(2, eval(A)); M := op(2, eval(A[op(1, N)])); minMN := min(op(2, M) - op(1, M), op(2, N) - op(1, N)); for j from op(1, M) to minMN do jp := j; t := abs(A[j][j]); for i from j+1 to op(2, M) do ab := abs(A[i][j]); if ab > t then jp := i; t := ab; end if; end do; pivot[j] := jp; if A[jp][j] = 0 then return 1; end if; if jp <> j then tA := eval(A[j]); A[j] := eval(A[jp]); A[jp] := eval(tA); end if; if j < op(2, M) then recp := 1.0 / A[j][j]; for k from j+1 to op(2, M) do A[k][j] := A[k][j]*recp; end do; end if; if j < minMN then for ii from j+1 to op(2, M) do Aii := A[ii]; Aj := A[j]; AiiJ := Aii[j]; for jj from j+1 to op(2, N) do Aii[jj] := Aii[jj] - AiiJ * Aj[jj]; end do; end do; end if; end do; return 0; end proc; solve := proc(LU::array, pvt::array, b::array) local M, N, ii, i, ip, sum, j; M := op(2, eval(LU)); N := op(2, eval(LU[op(1, M)])); ii := 0; for i from op(1, M) to op(2,M) do ip := pvt[i]; sum := b[ip]; b[ip] := b[i]; if ii = 0 then for j from ii to i-1 do sum := sum - LU[i][j] * b[j]; end do; else if sum = 0.0 then ii := i; end if; end if; b[i] := sum; end do; for i from op(2, N) by -1 to op(1, N) do sum := b[i]; for j from i+1 to op(2, N) do sum := sum - LU[i][j] * b[j]; end do; b[i] := sum / LU[i][i]; end do; end proc; end module: return m; end proc: # }}} kernel := module() # {{{ export measureFFT, measureMonteCarlo, measureSOR, measureSparseMatmult, measureLU, test; local RandomMatrix, RandomVector, CopyMatrix, NewVectorCopy, normabs, matvec, matvec3; measureFFT := proc(N::integer, mintime::float, R::`module`) local x, cycles, Q, i, EPS; x := RandomVector(2*N, R); cycles := 1; Q := Stopwatch(); while true do Q:-strt(); # print("here", cycles); for i from 0 to cycles-1 do # print("before:", x); smFFT():-transform(x); # forward transform # print("middle:", x); smFFT():-inverse(x); # backward transform # print("after:", x); quit; end do; # print("there"); Q:-stp(); if Q:-rd() >= mintime then break; end if; cycles := cycles * 2; end do; EPS := 1.0e-6; if smFFT():-test(x) / N > EPS then return 0.0; end if; return smFFT():-num_flops(N)*cycles / Q:-rd() * 1.0e-6; end proc; measureSOR := proc(N::integer, min_time::float, R::`module`) local Q, G, cycles; G := RandomMatrix(N, N, R); Q := Stopwatch(); cycles := 1; while true do Q:-strt(); # print("before: G=", G); SOR():-execute(1.25, G, cycles); # print("after: G=", G); quit; Q:-stp(); if Q:-rd() >= min_time then break; end if; cycles := cycles * 2; end do: return SOR():-num_flops(N, N, cycles) / Q:-rd() * 1.0e-6; end proc: measureMonteCarlo := proc(min_time, R) local Q, cycles, val; Q := Stopwatch(); cycles := 1; while true do Q:-strt(); val := MonteCarlo:-integrate(cycles); Q:-stp(); # print(val); if Q:-rd() >= min_time then break; end if; cycles := cycles * 2; end do; return MonteCarlo:-num_flops(cycles) / Q:-rd() * 1.0e-6; end proc; measureSparseMatmult := proc(N::integer, nz::integer, min_time::float, R::`module`) local x, y, nr, anz, val, col, row, r, rowr, step, i, Q, cycles; x := RandomVector(N, R); y := array(0..N - 1); nr := floor(nz / N); anz := nr * N; val := RandomVector(anz, R); col := array(0..anz - 1); row := array(0..N); row[0] := 0.0; for r from 0 to (N - 1) do rowr := row[r]; row[r + 1] := evalhf(rowr + nr); step := floor(r / nr); if step < 1 then step := 1 end if: for i from 0 to (nr - 1) do col[floor(rowr + i)] := evalhf(i * step); end do: end do: Q := Stopwatch(); cycles := 1.; while true do Q:-strt(); SparseCompRow():-matmult(y, val, row, eval(col), x, cycles); #print(y); quit; Q:-stp(); if Q:-rd() >= min_time then break; end if: cycles := cycles * 2; end do: return SparseCompRow():-num_flops(N, nz, cycles) / Q:-rd() * 1.0e-6; end proc: measureLU := proc(N::integer, min_time::float, R::`module`) local A, lu, pivot, Q, i, cycles, b, x, EPS; A := RandomMatrix(N, N, R); lu := array(0..N-1); for i from 0 to N-1 do lu[i] := array(0..N-1); end do; pivot := array(0..N-1); Q := Stopwatch(); cycles := 1; while true do Q:-strt(); for i from 0 to cycles-1 do CopyMatrix(lu, A); LU():-factor(lu, pivot); end do; Q:-stp(); if Q:-rd() >= min_time then break; end if; cycles := cycles * 2; end do: b := RandomVector(N, R); x := NewVectorCopy(b); LU():-solve(lu, pivot, x); EPS := 1.0e-6; if normabs(b, matvec(A,x)) / N > EPS then return 0.0; end if; return LU():-num_flops(N) * cycles / Q:-rd() * 1.0e-6; end proc: RandomMatrix := proc(M::integer, N::integer, R::`module`) local A, i, B, j; A := array(0..M-1); for i from 0 to (M - 1) do B := array(0..N-1); for j from 0 to N - 1 do B[j] := R:-nextDouble(); end do: A[i] := eval(B); end do: return A; end proc: RandomVector := proc(N::integer, R::`module`) local A, i; A := array(0..N - 1); for i from 0 to N - 1 do A[i] := R:-nextDouble(); end do: return eval(A); end proc: CopyMatrix := proc(B::array, A::array) local M, N, remainder, i, Bi, Ai, j; M := op(2, eval(A)); N := op(2, eval(A[op(1, M)])); remainder := irem (op(2,N)-op(1,N)+1, 4); for i from op(1, M) to op(2, M) do Bi := B[i]; Ai := A[i]; for j from 0 to remainder-1 do Bi[j] := Ai[j]; end do; for j from remainder by 4 to op(2, N)-1 do Bi[j] := Ai[j]; Bi[j+1] := Ai[j+1]; Bi[j+2] := Ai[j+2]; Bi[j+3] := Ai[j+3]; end do; end do; end proc; NewVectorCopy := proc(x::array) local N, y, i; N := op(2, eval(x)); y := array(N); for i from op(1, N) to op(2, N) do y[i] := x[i]; end do; return y; end proc; normabs := proc(x::array, y::array) local N, sum, i; N := op(2, eval(x)); sum := 0.0; for i from op(1, N) to op(2, N) do sum := sum + abs(x[i]-y[i]); end do; return sum; end proc; matvec := proc(A::array, x::array) local N, y; N := op(2, eval(x)); y := array(N); matvec3(A, x, y); return eval(y); end proc; matvec3 := proc(A::array, x::array, y::array) local M, N, i, sum, Ai, j; M := op(2, eval(A)); N := op(2, eval(A[op(1, M)])); for i from op(1, M) to op(2, M) do sum := 0.0; Ai := A[i]; for j from op(1, N) to op(2, N) do sum := sum + Ai[j] * x[j]; end do; y[i] := sum; end do; end proc; test := proc() local r, m, lu, i, p, b, x, EPS; r := Random(1); m := RandomMatrix(3, 3, r); lu := array(0..3-1); for i from 0 to 3-1 do lu[i] := array(0..3-1); end do; CopyMatrix(lu, m); p := array(0..3-1); print("m=", m); LU():-factor(lu, p); print("m=", eval(m), "p=", p); b := RandomVector(3, r); x := NewVectorCopy(b); print("b=", b); LU():-solve(lu, p, x); print("x=", x); EPS := 1.0e-5; print("matvec", matvec(m, x)); print("normabs", normabs(b, matvec(m,x))); if normabs(b, matvec(m,x)) / 3 > EPS then print("here "); return 0.0; end if; end proc; end module: # }}} commandline := module() # {{{ export main; main := proc(arg) local res, R, min_time, FFT_size, SOR_size, Sparse_size_M, Sparse_size_nz, LU_size; min_time := Constants:-RESOLUTION_DEFAULT; FFT_size := Constants:-FFT_SIZE; SOR_size := Constants:-SOR_SIZE; Sparse_size_M := Constants:-SPARSE_SIZE_M; Sparse_size_nz := Constants:-SPARSE_SIZE_nz; LU_size := Constants:-LU_SIZE; #POLY_size := Constants:-POLY_SIZE; #RecLU_size := Constants:-RecLU_SIZE; # if (args.length > 0) { # if (args[0].equalsIgnoreCase("-h") # || args[0].equalsIgnoreCase("-help")) { # print("Usage: [-large] [minimum_time]"); # return; # } # int current_arg = 0; # if (args[current_arg].equalsIgnoreCase("-large")) { # FFT_size = Constants.LG_FFT_SIZE; # SOR_size = Constants.LG_SOR_SIZE; # Sparse_size_M = Constants.LG_SPARSE_SIZE_M; # Sparse_size_nz = Constants.LG_SPARSE_SIZE_nz; # LU_size = Constants.LG_LU_SIZE; # POLY_size = Constants.LG_POLY_SIZE; # current_arg++; # } # if (args.length > current_arg) # min_time = Double.valueOf(args[current_arg]).doubleValue(); # } res := Array(0..7); R := Random(Constants:-RANDOM_SEED); print(); print("SciGMark 1.0 - Maple - specialized"); print(); res[1] := kernel:-measureFFT(FFT_size, min_time, R); if res[1] = 0.0 then print("FFT: ERROR, INVALID NUMERICAL RESULT!"); else print("FFT (", FFT_size, "): ", res[1]); end if; res[2] := kernel:-measureSOR(SOR_size, min_time, R); print("SOR (", SOR_size, "x", SOR_size, "): ", res[2]); res[3] := kernel:-measureMonteCarlo(min_time, R); print("Monte Carlo : ", res[3]); res[4] := kernel:-measureSparseMatmult(Sparse_size_M, Sparse_size_nz, min_time, R); print("Sparse matmult (N=", Sparse_size_M, "nz=", Sparse_size_nz, "):", res[4]); res[5] := kernel:-measureLU(LU_size, min_time, R); if res[5] = 0.0 then print("LU: ERROR, INVALID NUMERICAL RESULT!"); else print("LU (", LU_size, "x", LU_size, "): ", res[5]); end if; # res[6] = kernel.measureMultPoly(POLY_size, min_time); # print("PolyMult (N=" + POLY_size + "): " + res[6]); # res[7] = kernel.measureRecLU(RecLU_size, min_time, R); # System.out.print("RecLU (" + RecLU_size + "x" + RecLU_size + "): "); # if (res[7] == 0.0) # print(" ERROR, INVALID NUMERICAL RESULT!"); # else # print(res[7]); # res[0] = (res[1] + res[2] + res[3] + res[4] + res[5] + res[6] + res[7]) / 7; res[0] := (res[1] + res[2] + res[3] + res[4] + res[5]) / 5; print(); print("Composite Score: ", res[0]); end proc; end module: # }}} # {{{ Main program writeto("maple.txt");commandline:-main(); R := Random(11): kernel:-measureSOR(Constants:-SOR_SIZE, Constants:-RESOLUTION_DEFAULT, R); kernel:-measureMonteCarlo(Constants:-RESOLUTION_DEFAULT, R); kernel:-measureSparseMatmult(3, 5, 1., R); quit;