From 8552a17b21a16e4a675f6ca0699e88859842ccd0 Mon Sep 17 00:00:00 2001 From: inga-lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Sun, 16 Apr 2017 13:15:17 +0300 Subject: [PATCH] Microoptimization --- .../WhiteRabbit.UnmanagedBridge.cpp | 18 ++++---- dotnet/WhiteRabbit/Constants.cs | 2 +- dotnet/WhiteRabbit/MD5Digest.cs | 5 +- dotnet/WhiteRabbit/PhraseSet.cs | 46 ++++++++++++------- .../PrecomputedPermutationsGenerator.cs | 2 +- 5 files changed, 45 insertions(+), 28 deletions(-) diff --git a/dotnet/WhiteRabbit.UnmanagedBridge/WhiteRabbit.UnmanagedBridge.cpp b/dotnet/WhiteRabbit.UnmanagedBridge/WhiteRabbit.UnmanagedBridge.cpp index 71bf99f..76d3d8f 100644 --- a/dotnet/WhiteRabbit.UnmanagedBridge/WhiteRabbit.UnmanagedBridge.cpp +++ b/dotnet/WhiteRabbit.UnmanagedBridge/WhiteRabbit.UnmanagedBridge.cpp @@ -9,17 +9,19 @@ void WhiteRabbitUnmanagedBridge::MD5Unmanaged::ComputeMD5(unsigned __int32 * inp { #if AVX2 md5(input + 0 * 8 * 8, output + 0 * 8); + md5(input + 1 * 8 * 8, output + 0 * 8); #elif SIMD md5(input + 0 * 8 * 4, output + 0 * 4); md5(input + 1 * 8 * 4, output + 1 * 4); + if (input[2 * 8 * 4] != 0) + { + md5(input + 2 * 8 * 4, output + 0 * 4); + md5(input + 3 * 8 * 4, output + 1 * 4); + } #else - md5(input + 0 * 8, output + 0); - md5(input + 1 * 8, output + 1); - md5(input + 2 * 8, output + 2); - md5(input + 3 * 8, output + 3); - md5(input + 4 * 8, output + 4); - md5(input + 5 * 8, output + 5); - md5(input + 6 * 8, output + 6); - md5(input + 7 * 8, output + 7); + for (int i = 0; i < 16; i++) + { + md5(input + i * 8, output + i); + } #endif } diff --git a/dotnet/WhiteRabbit/Constants.cs b/dotnet/WhiteRabbit/Constants.cs index 6ba9d03..1894148 100644 --- a/dotnet/WhiteRabbit/Constants.cs +++ b/dotnet/WhiteRabbit/Constants.cs @@ -2,6 +2,6 @@ { internal class Constants { - public const int PhrasesPerSet = 8; + public const int PhrasesPerSet = 16; } } diff --git a/dotnet/WhiteRabbit/MD5Digest.cs b/dotnet/WhiteRabbit/MD5Digest.cs index 85959d3..7cfa311 100644 --- a/dotnet/WhiteRabbit/MD5Digest.cs +++ b/dotnet/WhiteRabbit/MD5Digest.cs @@ -12,7 +12,10 @@ var result = new uint[Constants.PhrasesPerSet]; fixed (uint* resultPointer = result) { - MD5Unmanaged.ComputeMD5((uint*)input.Buffer, resultPointer); + fixed (long* inputBuffer = input.Buffer) + { + MD5Unmanaged.ComputeMD5((uint*)inputBuffer, resultPointer); + } } return result; diff --git a/dotnet/WhiteRabbit/PhraseSet.cs b/dotnet/WhiteRabbit/PhraseSet.cs index 642f68e..691da4b 100644 --- a/dotnet/WhiteRabbit/PhraseSet.cs +++ b/dotnet/WhiteRabbit/PhraseSet.cs @@ -3,34 +3,46 @@ using System.Diagnostics; // Anagram representation optimized for MD5 - internal unsafe struct PhraseSet + internal struct PhraseSet { - public fixed long Buffer[4 * Constants.PhrasesPerSet]; + public long[] Buffer; - public PhraseSet(Word[] words, long[] permutations, int offset, int numberOfCharacters) + public unsafe PhraseSet(Word[] words, long[] permutations, int offset, int numberOfCharacters) { Debug.Assert(numberOfCharacters + words.Length - 1 < 27); + this.Buffer = new long[4 * Constants.PhrasesPerSet]; + fixed (long* bufferPointer = this.Buffer) { long* longBuffer = (long*)bufferPointer; int numberOfWords = words.Length; - for (var i = 0; i < Constants.PhrasesPerSet; i++) + + fixed (long* permutationsPointer = permutations) { - var permutation = permutations[offset + i]; - var cumulativeWordOffsetX4 = 0; - for (var j = 0; j < numberOfWords; j++) + var currentPermutationPointer = permutationsPointer + offset; + for (var i = 0; i < Constants.PhrasesPerSet; i++, currentPermutationPointer++) { - var currentWord = words[permutation & 15]; - permutation = permutation >> 4; - longBuffer[0] |= currentWord.Buffers[cumulativeWordOffsetX4 + 0]; - longBuffer[1] |= currentWord.Buffers[cumulativeWordOffsetX4 + 1]; - longBuffer[2] ^= currentWord.Buffers[cumulativeWordOffsetX4 + 2]; - longBuffer[3] ^= currentWord.Buffers[cumulativeWordOffsetX4 + 3]; - cumulativeWordOffsetX4 += currentWord.LengthX4; - } + var permutation = *currentPermutationPointer; + if (permutation == 0) + { + continue; + } + + var cumulativeWordOffsetX4 = 0; + for (var j = 0; j < numberOfWords; j++) + { + var currentWord = words[permutation & 15]; + permutation = permutation >> 4; + longBuffer[0] |= currentWord.Buffers[cumulativeWordOffsetX4 + 0]; + longBuffer[1] |= currentWord.Buffers[cumulativeWordOffsetX4 + 1]; + longBuffer[2] ^= currentWord.Buffers[cumulativeWordOffsetX4 + 2]; + longBuffer[3] ^= currentWord.Buffers[cumulativeWordOffsetX4 + 3]; + cumulativeWordOffsetX4 += currentWord.LengthX4; + } - longBuffer += 4; + longBuffer += 4; + } } var length = numberOfCharacters + numberOfWords - 1; @@ -51,7 +63,7 @@ } } - public byte[] GetBytes(int number) + public unsafe byte[] GetBytes(int number) { Debug.Assert(number < Constants.PhrasesPerSet); diff --git a/dotnet/WhiteRabbit/PrecomputedPermutationsGenerator.cs b/dotnet/WhiteRabbit/PrecomputedPermutationsGenerator.cs index 669c732..9286196 100644 --- a/dotnet/WhiteRabbit/PrecomputedPermutationsGenerator.cs +++ b/dotnet/WhiteRabbit/PrecomputedPermutationsGenerator.cs @@ -29,7 +29,7 @@ return original; } - return original.Concat(Enumerable.Repeat(original[0], chunkSize - (original.Length % chunkSize))).ToArray(); + return original.Concat(Enumerable.Repeat(default(T), chunkSize - (original.Length % chunkSize))).ToArray(); } private static long FormatPermutation(PermutationsGenerator.Permutation permutation)