-
-
Save KeenS/35345a4661dc696f467abd2de830568d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ smlsharp -v | |
SML# 3.4.0 (2017-08-31 19:31:44 JST) for x86_64-pc-linux-gnu with LLVM 3.7.1 | |
$ smlsharp -O3 inner_prod.sml -o inner_prod_smlsharp | |
$ ./inner_prod_smlsharp | |
compose | |
Time: | |
[Total] 9101 ms/10calls | |
[Average] 910.1 ms/call | |
loop | |
Time: | |
[Total] 935 ms/10calls | |
[Average] 93.5 ms/call | |
$ smlsharp -dinsertCheckGC=no -O3 inner_prod.sml -o inner_prod_smlsharp | |
$ ./inner_prod_smlsharp | |
compose | |
Time: | |
[Total] 3264 ms/10calls | |
[Average] 326.4 ms/call | |
loop | |
Time: | |
[Total] 732 ms/10calls | |
[Average] 73.2 ms/call | |
$ mlton | |
MLton 20130715 (built Fri Apr 28 06:06:34 UTC 2017 on lcy01-11) | |
$ mlton -output inner_prod_mlton inner_prod.sml | |
$ ./inner_prod_mlton | |
compose | |
Time: | |
[Total] 650 ms/10calls | |
[Average] 65 ms/call | |
loop | |
Time: | |
[Total] 48 ms/10calls | |
[Average] 4.8 ms/call | |
$ mlton -output inner_prod_mlton_opt -link-opt -O3 -cc-opt -O3 -codegen native inner_prod.sml | |
$ ./inner_prod_mlton_opt | |
compose | |
Time: | |
[Total] 654 ms/10calls | |
[Average] 65.4 ms/call | |
loop | |
Time: | |
[Total] 48 ms/10calls | |
[Average] 4.8 ms/call | |
$ sml inner_prod.sml | |
Standard ML of New Jersey v110.79 [built: Tue Aug 8 23:21:20 2017] | |
[opening inner_prod.sml] | |
[autoloading] | |
[library $SMLNJ-BASIS/basis.cm is stable] | |
[library $SMLNJ-BASIS/(basis.cm):basis-common.cm is stable] | |
[autoloading done] | |
compose | |
Time: | |
[Total] 3292 ms/10calls | |
[Average] 329.2 ms/call | |
loop | |
Time: | |
[Total] 32 ms/10calls | |
[Average] 3.2 ms/call | |
# data size is /10 ed to avoid stack overflow | |
$ ocamlopt --version | |
4.06.0 | |
$ ocamlfind ocamlopt -O3 -o inner_product_ocaml -thread -linkpkg -package core_bench,core inner_prod.ml | |
$ ./inner_product_ocaml | |
Estimated testing time 20s (2 benchmarks x 10s). Change using -quota SECS. | |
┌─────────┬─────────────┬──────────┬──────────┬──────────┬────────────┐ | |
│ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ | |
├─────────┼─────────────┼──────────┼──────────┼──────────┼────────────┤ | |
│ compose │ 13_845.52us │ 900.04kw │ 648.95kw │ 648.95kw │ 100.00% │ | |
│ loop │ 299.47us │ │ │ │ 2.16% │ | |
└─────────┴─────────────┴──────────┴──────────┴──────────┴────────────┘ | |
# data size is x10 ed for measure accuracy | |
$ ghc --version | |
The Glorious Glasgow Haskell Compilation System, version 8.0.2 | |
$ ghc -O3 inner_prod.hs -o inner_prod_hs | |
[1 of 1] Compiling Main ( inner_prod.hs, inner_prod.o ) | |
Linking inner_prod_hs ... | |
$ ./inner_prod_hs | |
compose (foldr): 0.829559656s | |
compose (foldl): 0.056206145s | |
loop : 0.055309029s |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.Exception | |
import Data.Time | |
innerProd1 :: [Int] -> [Int] -> Int | |
innerProd1 l1 l2 = foldr (+) 0 $ map (uncurry (*)) $ zip l1 l2 | |
innerProd1' :: [Int] -> [Int] -> Int | |
innerProd1' l1 l2 = foldl (+) 0 $ map (uncurry (*)) $ zip l1 l2 | |
innerProd2 :: [Int] -> [Int] -> Int | |
innerProd2 l1 l2 = loop l1 l2 0 | |
where loop [] _ acc = acc | |
loop _ [] acc = acc | |
loop (x:xs) (y:ys) acc = loop xs ys (acc + x*y) | |
clockSomething :: String -> a -> IO () | |
clockSomething name something = do | |
putStr $ name ++ ": " | |
start <- getCurrentTime | |
_ <- evaluate something | |
end <- getCurrentTime | |
print (diffUTCTime end start) | |
main :: IO () | |
main = do | |
clockSomething "compose (foldr)" $ innerProd1 list list | |
clockSomething "compose (foldl)" $ innerProd1' list list | |
clockSomething "loop " $ innerProd2 list list | |
where list = take (10 * 1000 * 1000) [1,1..] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let inner_prod1 (l1, l2) = List.fold_left (+) 0 (List.map (fun (a, b) -> a * b) (List.combine l1 l2)) | |
let inner_prod2 (l1, l2) = List.fold_left2 (fun acc a b -> acc + a * b) 0 l1 l2 | |
open Core_bench | |
let () = let list = let rec loop acc = function | |
0 -> acc | |
| n -> loop (1::acc) (n-1) | |
in loop [] (100 * 1000) | |
in | |
Core.Command.run (Bench.make_command [ | |
Bench.Test.create ~name: "compose" | |
(fun () -> inner_prod1 (list, list)); | |
Bench.Test.create ~name: "loop" | |
(fun () -> inner_prod2 (list, list)) | |
]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_require "basis.smi" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
structure Benchmark = | |
struct | |
fun repeat 0 f = () | |
| repeat n f = (f ();repeat (n - 1) f) | |
fun bench n f = let | |
val startTime = Time.now () | |
val _ = repeat n f | |
val endTime = Time.now () | |
in | |
Time.toMilliseconds (Time.-(endTime, startTime)) | |
end | |
fun benchmark name n f = let | |
val time = bench n f | |
in | |
print (name ^ "\n"); | |
print (" Time:\n"); | |
print (" [Total] " ^ (LargeInt.toString time) ^ " ms/" ^ (Int.toString n) ^ "calls\n"); | |
print (" [Average] " ^ (Real.toString((Real.fromLargeInt time) / (Real.fromInt n))) ^ " ms/call\n") | |
end | |
fun nChars n char = CharArray.vector(CharArray.array(n, char)) | |
fun toWidth width str = let | |
val len = String.size str | |
in | |
if len < width | |
then str ^ (nChars (width - len) #" ") | |
else str | |
end | |
fun histLine width base value = | |
(nChars (Int.fromLarge(width * value div base)) #"*") ^ "\n" | |
fun benchset name n fs = let | |
val res = List.map (fn (label, f) => (label, bench n f)) fs | |
val max = List.foldl (fn ((_, time), m) => LargeInt.max(time, m)) 0 res | |
val maxLen = List.foldl (fn ((label, _), m) => Int.max(String.size label, m)) 0 fs | |
in | |
print "name:\n"; | |
print ((nChars ((String.size " ") + maxLen) #"-") ^ "+" ^ (nChars ((String.size "|") + 50) #"-") ^ "\n"); | |
app (fn (label, time) => print(" " ^ (toWidth maxLen label) ^ "|" ^(histLine (50:LargeInt.int) max time))) res; | |
print ((nChars ((String.size " ") + maxLen) #"-") ^ "+" ^ (nChars ((String.size "|") + 50) #"-") ^ "\n") | |
end | |
end | |
val inner_product1 = List.foldl op+ 0 o List.map op* o ListPair.zip | |
fun inner_product2 (l1, l2) = let | |
fun loop [] _ acc = acc | |
| loop _ [] acc = acc | |
| loop (x::xs) (y::ys) acc = loop xs ys (acc + x*y) | |
in | |
loop l1 l2 0 | |
end | |
val _ = let | |
(* [1, 1, 1, ...] *) | |
val list = List.tabulate(1000 * 1000, fn _ => 1) | |
in | |
Benchmark.benchmark "compose" 10 (fn _ => inner_product1(list, list)); | |
Benchmark.benchmark "loop" 10 (fn _ => inner_product2(list, list)) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment