Advertisement
Guest User

Untitled

a guest
Sep 30th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.04 KB | None | 0 0
  1. using BenchmarkDotNet.Attributes;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Numerics;
  6. using System.Runtime.CompilerServices;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using BenchmarkDotNet.Configs;
  10. using BenchmarkDotNet.Jobs;
  11. using BenchmarkDotNet.Running;
  12. using Xunit;
  13.  
  14. namespace DeBruijnBenchmark
  15. {
  16. public class Program
  17. {
  18. public static void Main()
  19. {
  20. Console.WriteLine(Vector.IsHardwareAccelerated);
  21. if (!Vector.IsHardwareAccelerated) throw new ArgumentException();
  22. Console.WriteLine(FirstByteBenchmark._vectors[0]);
  23. BenchmarkRunner.Run<FirstByteBenchmark>();
  24. }
  25. }
  26. public class Config : ManualConfig
  27. {
  28. public Config()
  29. {
  30. // gets too slow otherwise
  31. Add(Job.Default
  32. .WithLaunchCount(1) // benchmark process will be launched only once
  33. .WithIterationTime(200) // 200ms per iteration
  34. .WithWarmupCount(10) // 10 warmup iteration
  35. .WithTargetCount(10) // 10 target iteration
  36. );
  37. }
  38. }
  39.  
  40. [Config(typeof(Config))]
  41. public class FirstByteBenchmark
  42. {
  43. private static readonly byte[] Debruijn64Xor =
  44. {
  45. 0, 5, 0, 7, 6, 3, 0, 7,
  46. 7, 6, 5, 4, 3, 2, 0, 7,
  47. 6, 7, 4, 6, 6, 5, 2, 5,
  48. 4, 4, 3, 2, 2, 1, 0, 7,
  49. 5, 6, 3, 7, 5, 4, 1, 6,
  50. 4, 6, 2, 5, 3, 2, 1, 5,
  51. 3, 4, 1, 4, 2, 3, 1, 3,
  52. 1, 2, 1, 1, 0, 0, 0, 7,
  53. };
  54.  
  55. static readonly byte[] Debruijn64Long =
  56. {
  57. 0, 0, 0, 7, 0, 4, 7, 5, 3, 0, 2, 4, 0, 7, 1, 5,
  58. 7, 3, 2, 0, 2, 2, 4, 2, 6, 1, 7, 4, 3, 1, 6, 4,
  59. 7, 6, 3, 5, 3, 2, 0, 1, 7, 2, 1, 2, 6, 4, 3, 4,
  60. 6, 5, 3, 1, 7, 1, 6, 4, 5, 3, 1, 6, 5, 6, 5, 5,
  61. };
  62.  
  63. const ulong DEBRUIJN_SEQ64 = 0x03f79d71b4cb0a89;
  64. const long DEBRUIJN_SEQ64L = 0x26752B916FC7B0D;
  65.  
  66. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  67. private static int DebruijnFindByteXor(ulong v)
  68. {
  69. return Debruijn64Xor[((v ^ (v - 1)) * DEBRUIJN_SEQ64) >> 58];
  70. }
  71.  
  72. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  73. private static int DebruijnFindByte(long v)
  74. {
  75. return Debruijn64Long[(ulong)((v & -v) * DEBRUIJN_SEQ64L) >> 58];
  76. }
  77.  
  78. /// <summary>
  79. /// Find first byte
  80. /// </summary>
  81. /// <param name="byteEquals"></param >
  82. /// <returns>The first index of the result vector</returns>
  83. /// <exception cref="InvalidOperationException">byteEquals = 0</exception>
  84. private static int FindFirstEqualByteOld(ref Vector<byte> byteEquals)
  85. {
  86. // Quasi-tree search
  87.  
  88. var vector64 = Vector.AsVectorInt64(byteEquals);
  89. for (var i = 0; i < Vector<long>.Count; i++)
  90. {
  91. var longValue = vector64[i];
  92. if (longValue == 0) continue;
  93.  
  94. return (i << 3) +
  95. ((longValue & 0x00000000ffffffff) > 0
  96. ? (longValue & 0x000000000000ffff) > 0
  97. ? (longValue & 0x00000000000000ff) > 0 ? 0 : 1
  98. : (longValue & 0x0000000000ff0000) > 0 ? 2 : 3
  99. : (longValue & 0x0000ffff00000000) > 0
  100. ? (longValue & 0x000000ff00000000) > 0 ? 4 : 5
  101. : (longValue & 0x00ff000000000000) > 0 ? 6 : 7);
  102. }
  103. throw new InvalidOperationException();
  104. }
  105.  
  106. /// <summary>
  107. /// Find first byte
  108. /// </summary>
  109. /// <param name="byteEquals"></param >
  110. /// <returns>The first index of the result vector</returns>
  111. /// <exception cref="InvalidOperationException">byteEquals = 0</exception>
  112.  
  113. internal static int FindFirstEqualByteDeBrujinXor(ref Vector<byte> byteEquals)
  114. {
  115. var vector64 = Vector.AsVectorUInt64(byteEquals);
  116. for (var i = 0; i < Vector<ulong>.Count; i++)
  117. {
  118. var longValue = vector64[i];
  119. if (longValue == 0) continue;
  120.  
  121. return (i << 3) + DebruijnFindByteXor(longValue);
  122. }
  123. throw new InvalidOperationException();
  124. }
  125.  
  126. /// <summary>
  127. /// Find first byte
  128. /// </summary>
  129. /// <param name="byteEquals"></param >
  130. /// <returns>The first index of the result vector</returns>
  131. /// <exception cref="InvalidOperationException">byteEquals = 0</exception>
  132.  
  133. internal static int FindFirstEqualByteDeBrujin(ref Vector<byte> byteEquals)
  134. {
  135. var vector64 = Vector.AsVectorInt64(byteEquals);
  136. for (var i = 0; i < Vector<long>.Count; i++)
  137. {
  138. var longValue = vector64[i];
  139. if (longValue == 0) continue;
  140.  
  141. return (i << 3) + DebruijnFindByte(longValue);
  142. }
  143. throw new InvalidOperationException();
  144. }
  145.  
  146. internal static int FindFirstByteNaive(byte[] bytes)
  147. {
  148. for (int i = 0; i < bytes.Length; i++)
  149. {
  150. if (bytes[i] != 0) return i;
  151. }
  152. throw new InvalidOperationException();
  153. }
  154.  
  155.  
  156.  
  157. public static readonly byte[][] _vectors = InitVectors();
  158.  
  159. static byte[][] InitVectors()
  160. {
  161. int vbCount = Vector<byte>.Count;
  162. var vectors = new byte[vbCount][];
  163. for (int i = 0; i < vectors.Length; i++)
  164. {
  165. byte[] vectorData = new byte[vbCount];
  166. vectorData[i] = 1;
  167. vectors[i] = vectorData;
  168. }
  169. return vectors;
  170. }
  171.  
  172.  
  173. //static Vector<byte>[] InitVectors()
  174. //{
  175. // int vbCount = Vector<byte>.Count;
  176. // var vectors = new Vector<byte>[vbCount];
  177. // for (int i = 0; i < vectors.Length; i++)
  178. // {
  179. // byte[] vectorData = new byte[vbCount];
  180. // vectorData[i] = 1;
  181. // vectors[i] = new Vector<byte>(vectorData);
  182. // }
  183. // return vectors;
  184. //}
  185.  
  186.  
  187.  
  188.  
  189. [Params(31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)]
  190. public int ByteSet { get; set; }
  191.  
  192.  
  193. [Benchmark]
  194. public int FirstByteVector()
  195. {
  196. var bytes = _vectors[ByteSet];
  197. var vector = new Vector<byte>(bytes);
  198. return FindFirstEqualByteOld(ref vector);
  199. }
  200.  
  201. [Benchmark]
  202. public int FirstByteDeBruijnXor()
  203. {
  204. var bytes = _vectors[ByteSet];
  205. var vector = new Vector<byte>(bytes);
  206. return FindFirstEqualByteDeBrujinXor(ref vector);
  207. }
  208.  
  209. [Benchmark]
  210. public int FirstByteDeBruijnClassic()
  211. {
  212. var bytes = _vectors[ByteSet];
  213. var vector = new Vector<byte>(bytes);
  214. return FindFirstEqualByteDeBrujin(ref vector);
  215. }
  216.  
  217. [Benchmark]
  218. public int FindFirstByteNaive()
  219. {
  220. var bytes = _vectors[ByteSet];
  221. return FindFirstByteNaive(bytes);
  222.  
  223. }
  224.  
  225. [Theory]
  226. [InlineData(0)]
  227. [InlineData(1)]
  228. [InlineData(2)]
  229. [InlineData(3)]
  230. [InlineData(4)]
  231. [InlineData(5)]
  232. [InlineData(6)]
  233. [InlineData(7)]
  234. [InlineData(8)]
  235. [InlineData(9)]
  236. [InlineData(10)]
  237. [InlineData(11)]
  238. [InlineData(12)]
  239. [InlineData(13)]
  240. [InlineData(14)]
  241. [InlineData(15)]
  242. public void AssertFirstByte(int b)
  243. {
  244. var bytes = _vectors[b];
  245. var vvalue = new Vector<byte>(bytes);
  246. int dbPos = FindFirstEqualByteDeBrujin(ref vvalue);
  247. int vPos = FindFirstEqualByteOld(ref vvalue);
  248. int dbxPos = FindFirstEqualByteDeBrujinXor(ref vvalue);
  249. int pos = FindFirstByteNaive(bytes);
  250. Assert.Equal(b, dbPos);
  251. Assert.Equal(b, vPos);
  252. Assert.Equal(b, dbxPos);
  253. Assert.Equal(b, pos);
  254. }
  255. }
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement