Last active
August 29, 2015 14:19
-
-
Save axelheer/3b701c91271b7c762586 to your computer and use it in GitHub Desktop.
Basic benchmark for BigInteger
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
using System.Diagnostics; | |
namespace System.Numerics.Benchmark | |
{ | |
public class Program | |
{ | |
private static readonly Random s_random = new Random(1138); | |
private static int s_bits = 4096; | |
private static int s_vals = 100; | |
private static int s_runs = 10; | |
public static void Main(string[] args) | |
{ | |
var op = "mul"; | |
if (args.Length > 0) | |
op = args[0].ToLowerInvariant(); | |
if (args.Length > 1) | |
s_bits = TryParse(args[1]); | |
if (args.Length > 2) | |
s_vals = TryParse(args[2]); | |
if (args.Length > 3) | |
s_runs = TryParse(args[3]); | |
Console.WriteLine("operation: {0}", op); | |
Console.WriteLine("# of bits: {0}", s_bits); | |
Console.WriteLine("# of vals: {0}", s_vals); | |
Console.WriteLine("# of runs: {0}", s_runs); | |
switch (op) | |
{ | |
case "add": | |
Benchmark(s_bits, s_bits, 0, | |
(a, b, _) => BigInteger.Add(a, b)); | |
break; | |
case "sub": | |
Benchmark(s_bits, s_bits, 0, | |
(a, b, _) => BigInteger.Subtract(a, b)); | |
break; | |
case "mul": | |
Benchmark(s_bits, s_bits, 0, | |
(a, b, _) => BigInteger.Multiply(a, b)); | |
break; | |
case "squ": | |
Benchmark(s_bits, 0, 0, | |
(a, _, __) => BigInteger.Multiply(a, a)); | |
break; | |
case "div": | |
Benchmark(s_bits, s_bits / 2 + 1, 0, | |
(a, b, _) => BigInteger.Divide(a, b)); | |
break; | |
case "mod": | |
Benchmark(s_bits, s_bits / 2 + 1, 0, | |
(a, b, _) => BigInteger.Remainder(a, b)); | |
break; | |
case "gcd": | |
Benchmark(s_bits, s_bits, 0, | |
(a, b, _) => BigInteger.GreatestCommonDivisor(a, b)); | |
break; | |
case "log": | |
Benchmark(s_bits, 0, 0, | |
(a, _, __) => BigInteger.Log(a)); | |
break; | |
case "modpow": | |
Benchmark(s_bits, s_bits, s_bits, | |
(a, b, c) => BigInteger.ModPow(a, b, c)); | |
break; | |
} | |
} | |
private static void Benchmark( | |
int leftSize, int rightSize, int otherSize, | |
Action<BigInteger, BigInteger, BigInteger> run) | |
{ | |
var left = new BigInteger[s_vals]; | |
var right = new BigInteger[s_vals]; | |
var other = new BigInteger[s_vals]; | |
// seed test values | |
for (var i = 0; i < s_vals; i++) | |
{ | |
left[i] = RandomInteger(leftSize); | |
right[i] = RandomInteger(rightSize); | |
other[i] = RandomInteger(otherSize); | |
} | |
Console.WriteLine(); | |
Console.Write("benchmark: "); | |
// run benchmarks | |
var result = long.MaxValue; | |
for (var j = 0; j < s_runs; j++) | |
{ | |
var watch = new Stopwatch(); | |
watch.Start(); | |
for (var i = 0; i < s_vals; i++) | |
run(left[i], right[i], other[i]); | |
watch.Stop(); | |
if (watch.ElapsedMilliseconds < result) | |
result = watch.ElapsedMilliseconds; | |
} | |
// tada! | |
Console.WriteLine("{0} ms / {1} ops", result, s_vals); | |
Console.WriteLine(); | |
} | |
private static BigInteger RandomInteger(int bits) | |
{ | |
if (bits <= 0) | |
return BigInteger.Zero; | |
var value = new byte[(bits + 7) / 8 + 1]; | |
s_random.NextBytes(value); | |
value[value.Length - 1] = 0x00; | |
var result = new BigInteger(value); | |
return result.IsZero ? BigInteger.One : result; | |
} | |
private static int TryParse(string value) | |
{ | |
var result = default(int); | |
if (int.TryParse(value, out result) && result > 0) | |
return result; | |
return 1; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment