fork download
  1. using System;
  2. using System.Linq.Expressions;
  3. using System.Diagnostics;
  4.  
  5. static class Program
  6. {
  7. static void Main()
  8. {
  9. try {
  10. var test = new double[1000, 1000];
  11.  
  12. var m1 = new Matrix1<double>();
  13. var m2 = new Matrix2<double>();
  14. var mn = new MatrixN();
  15.  
  16. // warm up
  17. m1.Add(test, test);
  18. m2.Add(test, test);
  19. mn.Add(test, test);
  20.  
  21. for (var j = 0; j<2; j++) {
  22. Stopwatch swE = new Stopwatch(), swD = new Stopwatch(), swN = new Stopwatch();
  23.  
  24. swE.Start();
  25. for (int i=0; i<100; i++)
  26. m1.Add(test, test);
  27. swE.Stop();
  28.  
  29. swD.Start();
  30. for (int i=0; i<100; i++)
  31. m2.Add(test, test);
  32. swD.Stop();
  33.  
  34. swN.Start();
  35. for (int i=0; i<100; i++)
  36. mn.Add(test, test);
  37. swN.Stop();
  38.  
  39. Console.WriteLine($"Simple way: elapsed time {swE.Elapsed}");
  40. Console.WriteLine($"Complex way: elapsed time {swD.Elapsed}");
  41. Console.WriteLine($"Non-generic way: elapsed time {swN.Elapsed}");
  42. }
  43. } catch (Exception ex) {
  44. Console.WriteLine(ex);
  45. }
  46. }
  47. }
  48.  
  49. class Matrix1<T>
  50. {
  51. static readonly Func<T, T, T> add;
  52.  
  53. static Matrix1()
  54. {
  55. var a = Expression.Parameter(typeof(T));
  56. var b = Expression.Parameter(typeof(T));
  57. add = Expression.Lambda<Func<T, T, T>>(Expression.Add(a, b), a, b).Compile();
  58. }
  59.  
  60. public void Add(T[,] a, T[,] b)
  61. {
  62. int lb0 = a.GetLowerBound(0),
  63. ub0 = a.GetUpperBound(0),
  64. lb1 = a.GetLowerBound(1),
  65. ub1 = a.GetUpperBound(1);
  66.  
  67. for (var i = lb0; i<=ub0; i++)
  68. for (var j = lb1; j<=ub1; j++)
  69. a[i,j] = add(a[i,j], b[i,j]);
  70. }
  71. }
  72.  
  73. class Matrix2<T>
  74. {
  75. delegate void MatrixOperation (int lb0, int ub0, int lb1, int ub1, T[,] a, T[,] b);
  76. static readonly MatrixOperation add;
  77.  
  78. static Expression MakeRangeFor(Expression min, Expression max, Func<Expression, Expression> body) {
  79. var i = Expression.Variable(min.Type);
  80. var exit = Expression.Label();
  81. return Expression.Block(new[]{ i },
  82. Expression.Assign(i, min),
  83. Expression.Loop(
  84. Expression.Block(
  85. body(i),
  86. Expression.Condition(
  87. Expression.LessThanOrEqual(Expression.PreIncrementAssign(i), max),
  88. Expression.Empty(),
  89. Expression.Break(exit)
  90. )
  91. ),
  92. )
  93. );
  94. }
  95.  
  96. static Matrix2()
  97. {
  98. var lb0 = Expression.Parameter(typeof(int));
  99. var ub0 = Expression.Parameter(typeof(int));
  100. var lb1 = Expression.Parameter(typeof(int));
  101. var ub1 = Expression.Parameter(typeof(int));
  102. var a = Expression.Parameter(typeof(T[,]));
  103. var b = Expression.Parameter(typeof(T[,]));
  104.  
  105. add = Expression.Lambda<MatrixOperation>(
  106. MakeRangeFor(lb0, ub0, i =>
  107. MakeRangeFor(lb1, ub1, j =>
  108. Expression.AddAssign(
  109. Expression.ArrayAccess(a, i, j),
  110. Expression.ArrayAccess(b, i, j)
  111. )
  112. )
  113. ),
  114. lb0, ub0, lb1, ub1, a, b).Compile();
  115. }
  116.  
  117. public void Add(T[,] a, T[,] b)
  118. {
  119. int lb0 = a.GetLowerBound(0),
  120. ub0 = a.GetUpperBound(0),
  121. lb1 = a.GetLowerBound(1),
  122. ub1 = a.GetUpperBound(1);
  123.  
  124. add(lb0, ub0, lb1, ub1, a, b);
  125. }
  126. }
  127.  
  128. class MatrixN
  129. {
  130. public void Add(double[,] a, double[,] b)
  131. {
  132. int lb0 = a.GetLowerBound(0),
  133. ub0 = a.GetUpperBound(0),
  134. lb1 = a.GetLowerBound(1),
  135. ub1 = a.GetUpperBound(1);
  136.  
  137. for (var i = lb0; i<=ub0; i++)
  138. for (var j = lb1; j<=ub1; j++)
  139. a[i,j] += b[i,j];
  140. }
  141. }
  142.  
Success #stdin #stdout 4.93s 31840KB
stdin
Standard input is empty
stdout
Simple way:      elapsed time 00:00:01.0461595
Complex way:     elapsed time 00:00:00.7827535
Non-generic way: elapsed time 00:00:00.5965895
Simple way:      elapsed time 00:00:01.0389834
Complex way:     elapsed time 00:00:00.7882222
Non-generic way: elapsed time 00:00:00.6038098