microoptimization

master
Inga 🏳‍🌈 7 years ago
parent 7f6aeb21bf
commit c919172ac7
  1. 8
      README.md
  2. 4
      dotnet/WhiteRabbit.UnmanagedBridge/WhiteRabbit.UnmanagedBridge.cpp
  3. 2
      dotnet/WhiteRabbit.UnmanagedBridge/WhiteRabbit.UnmanagedBridge.h
  4. 16
      dotnet/WhiteRabbit.UnmanagedBridge/phraseset.cpp
  5. 2
      dotnet/WhiteRabbit.UnmanagedBridge/phraseset.h
  6. 40
      dotnet/WhiteRabbit/PhraseSet.cs
  7. 4
      dotnet/WhiteRabbit/StringsProcessor.cs

@ -47,10 +47,10 @@ Number of words|Time to check all anagrams no longer than that|Time to solve "ea
---------------|----------------------------------------------|-------------------------|-----------------------------------|-------------------------|--------------------------------------------- ---------------|----------------------------------------------|-------------------------|-----------------------------------|-------------------------|---------------------------------------------
3|0.04s||||4560 3|0.04s||||4560
4|0.45s|||0.08s|7,431,984 4|0.45s|||0.08s|7,431,984
5|12s|0.15s|0.06s|0.3s|1,347,437,484 5|11.7s|0.15s|0.06s|0.3s|1,347,437,484
6|6.5 minutes|1.2s|0.2s|3s|58,405,904,844 6|6.5 minutes|1.2s|0.2s|2.9s|58,405,904,844
7|2 hours|7s|0.9s|19s|1,070,307,744,114 7|2 hours|6.7s|0.9s|19s|1,070,307,744,114
8|21.5 hours|25s|2.6s|80s|10,893,594,396,594 8|21.5 hours|25s|2.6s|79s|10,893,594,396,594
9||2.5 minutes|13s|9.5 minutes|70,596,864,409,954 9||2.5 minutes|13s|9.5 minutes|70,596,864,409,954
10||5 minutes|21s|17.5 minutes|314,972,701,475,754 10||5 minutes|21s|17.5 minutes|314,972,701,475,754

@ -27,7 +27,7 @@ void WhiteRabbitUnmanagedBridge::MD5Unmanaged::ComputeMD5(unsigned __int32 * inp
#endif #endif
} }
void WhiteRabbitUnmanagedBridge::MD5Unmanaged::FillPhraseSet(__int64* bufferPointer, __int64* allWordsPointer, __int32* wordIndexes, unsigned __int64* permutationsPointer, int numberOfCharacters, int numberOfWords) void WhiteRabbitUnmanagedBridge::MD5Unmanaged::FillPhraseSet(unsigned __int64* initialBufferPointer, unsigned __int64* bufferPointer, unsigned __int64* allWordsPointer, __int32* wordIndexes, unsigned __int64* permutationsPointer, int numberOfWords)
{ {
fillPhraseSet(bufferPointer, (unsigned __int64*)allWordsPointer, wordIndexes, permutationsPointer, numberOfCharacters, numberOfWords); fillPhraseSet(initialBufferPointer, bufferPointer, allWordsPointer, wordIndexes, permutationsPointer, numberOfWords);
} }

@ -13,6 +13,6 @@ namespace WhiteRabbitUnmanagedBridge {
public: public:
literal int PhrasesPerSet = PHRASES_PER_SET; literal int PhrasesPerSet = PHRASES_PER_SET;
static void ComputeMD5(unsigned int* input); static void ComputeMD5(unsigned int* input);
static void FillPhraseSet(__int64* bufferPointer, __int64* allWordsPointer, __int32* wordIndexes, unsigned __int64* permutationsPointer, int numberOfCharacters, int numberOfWords); static void FillPhraseSet(unsigned __int64* initialBufferPointer, unsigned __int64* bufferPointer, unsigned __int64* allWordsPointer, __int32* wordIndexes, unsigned __int64* permutationsPointer, int numberOfWords);
}; };
} }

@ -27,12 +27,12 @@
#define INIT_WORD(phraseNumber) \ #define INIT_WORD(phraseNumber) \
auto permutation = permutationsPointer[phraseNumber]; \ auto permutation = permutationsPointer[phraseNumber]; \
unsigned __int64 cumulativeWordOffset = 0; \ unsigned __int64 cumulativeWordOffset = 0; \
auto phrase = _mm256_set1_epi32(0); auto phrase = avx2initialBuffer[phraseNumber];
#define PROCESS_WORD(phraseNumber, wordNumber) \ #define PROCESS_WORD(phraseNumber, wordNumber) \
{ \ { \
auto currentWord = allWordsPointer + wordIndexes[permutation % 16] * 128; \ auto currentWord = allWordsPointer + wordIndexes[permutation % 16] * 128; \
phrase = _mm256_or_si256(phrase, *(__m256i*)(currentWord + cumulativeWordOffset)); \ phrase = _mm256_xor_si256(phrase, *(__m256i*)(currentWord + cumulativeWordOffset)); \
permutation >>= 4; \ permutation >>= 4; \
cumulativeWordOffset += currentWord[127]; \ cumulativeWordOffset += currentWord[127]; \
} }
@ -118,8 +118,9 @@
#define REPEAT_WORDS10(phraseNumber) REPEAT_WORDS(phraseNumber, REPEAT_WORDS_SIMPLE10) #define REPEAT_WORDS10(phraseNumber) REPEAT_WORDS(phraseNumber, REPEAT_WORDS_SIMPLE10)
void fillPhraseSet(__int64* bufferPointer, unsigned __int64* allWordsPointer, __int32* wordIndexes, unsigned __int64* permutationsPointer, int numberOfCharacters, int numberOfWords) void fillPhraseSet(unsigned __int64* initialBufferPointer, unsigned __int64* bufferPointer, unsigned __int64* allWordsPointer, __int32* wordIndexes, unsigned __int64* permutationsPointer, int numberOfWords)
{ {
auto avx2initialBuffer = (__m256i*)initialBufferPointer;
auto avx2buffer = (__m256i*)bufferPointer; auto avx2buffer = (__m256i*)bufferPointer;
switch (numberOfWords) switch (numberOfWords)
@ -155,15 +156,6 @@ void fillPhraseSet(__int64* bufferPointer, unsigned __int64* allWordsPointer, __
REPEAT_PHRASES(REPEAT_WORDS10); REPEAT_PHRASES(REPEAT_WORDS10);
break; break;
} }
auto length = numberOfCharacters + numberOfWords - 1;
auto lengthInBits = (unsigned __int32)(length << 3);
#define FILL_PHRASE_LAST_BYTE(phraseNumber) ((unsigned char*)bufferPointer)[length + phraseNumber * 32] = 128;
#define FILL_PHRASE_SET_LENGTH(phraseNumber) ((unsigned __int32*)bufferPointer)[7 + phraseNumber * 8] = lengthInBits;
REPEAT_PHRASES(FILL_PHRASE_LAST_BYTE);
REPEAT_PHRASES(FILL_PHRASE_SET_LENGTH);
} }
#pragma managed #pragma managed

@ -1,3 +1,3 @@
#pragma once #pragma once
void fillPhraseSet(__int64* bufferPointer, unsigned __int64* allWordsPointer, __int32* wordIndexes, unsigned __int64* permutationsPointer, int numberOfCharacters, int numberOfWords); void fillPhraseSet(unsigned __int64* initialBufferPointer, unsigned __int64* bufferPointer, unsigned __int64* allWordsPointer, __int32* wordIndexes, unsigned __int64* permutationsPointer, int numberOfWords);

@ -1,6 +1,7 @@
namespace WhiteRabbit namespace WhiteRabbit
{ {
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using WhiteRabbitUnmanagedBridge; using WhiteRabbitUnmanagedBridge;
@ -17,11 +18,23 @@
this.Buffer = new uint[8 * length]; this.Buffer = new uint[8 * length];
} }
public unsafe void FillPhraseSet(Word[] allWords, int[] wordIndexes, ulong[] permutations, int permutationOffset, int numberOfCharacters) public unsafe void InitPhraseSet(int numberOfCharacters, int numberOfWords)
{ {
Debug.Assert(numberOfCharacters + wordIndexes.Length - 1 < 27);
fixed (uint* bufferPointer = this.Buffer) fixed (uint* bufferPointer = this.Buffer)
{
var length = (uint)(numberOfCharacters + numberOfWords - 1);
var lengthInBits = (uint)(length << 3);
for (var i = 0; i < this.Length; i++)
{
bufferPointer[7 + i * 8] = lengthInBits;
((byte*)bufferPointer)[length + i * 32] = 128 ^ ' ';
}
}
}
public unsafe void FillPhraseSet(PhraseSet initial, Word[] allWords, int[] wordIndexes, ulong[] permutations, int permutationOffset)
{
fixed (uint* bufferPointer = this.Buffer, initialBufferPointer = initial.Buffer)
{ {
fixed (ulong* permutationsPointer = permutations) fixed (ulong* permutationsPointer = permutations)
{ {
@ -30,11 +43,11 @@
fixed (Word* allWordsPointer = allWords) fixed (Word* allWordsPointer = allWords)
{ {
MD5Unmanaged.FillPhraseSet( MD5Unmanaged.FillPhraseSet(
(long*)bufferPointer, (ulong*)initialBufferPointer,
(long*)allWordsPointer, (ulong*)bufferPointer,
(ulong*)allWordsPointer,
wordIndexesPointer, wordIndexesPointer,
permutationsPointer + permutationOffset, permutationsPointer + permutationOffset,
numberOfCharacters,
wordIndexes.Length); wordIndexes.Length);
} }
} }
@ -58,9 +71,9 @@
public unsafe byte[] GetBytes(int number) public unsafe byte[] GetBytes(int number)
{ {
Debug.Assert(number < Constants.PhrasesPerSet); Debug.Assert(number < this.Length);
fixed(uint* bufferPointer = this.Buffer) fixed (uint* bufferPointer = this.Buffer)
{ {
var phrasePointer = bufferPointer + 8 * number; var phrasePointer = bufferPointer + 8 * number;
var length = 0; var length = 0;
@ -82,5 +95,16 @@
return result; return result;
} }
} }
public unsafe string DebugBytes(int number)
{
Debug.Assert(number < this.Length);
fixed (uint* bufferPointer = this.Buffer)
{
var bytes = (byte*)bufferPointer;
return string.Concat(Enumerable.Range(32 * number, 32).Select(i => bytes[i].ToString("X2")));
}
}
} }
} }

@ -120,6 +120,8 @@
private void ProcessSum(int[] sum, Action<PhraseSet> action) private void ProcessSum(int[] sum, Action<PhraseSet> action)
{ {
var initialPhraseSet = new PhraseSet(Constants.PhrasesPerSet);
initialPhraseSet.InitPhraseSet(this.NumberOfCharacters, sum.Length);
var phraseSet = new PhraseSet(Constants.PhrasesPerSet); var phraseSet = new PhraseSet(Constants.PhrasesPerSet);
var filter = ComputeFilter(sum); var filter = ComputeFilter(sum);
var wordsVariants = this.ConvertVectorsToWordIndexes(sum); var wordsVariants = this.ConvertVectorsToWordIndexes(sum);
@ -130,7 +132,7 @@
var permutations = PrecomputedPermutationsGenerator.HamiltonianPermutations(wordsArray.Length, filter); var permutations = PrecomputedPermutationsGenerator.HamiltonianPermutations(wordsArray.Length, filter);
for (var i = 0; i < permutations.Length; i += Constants.PhrasesPerSet) for (var i = 0; i < permutations.Length; i += Constants.PhrasesPerSet)
{ {
phraseSet.FillPhraseSet(this.AllWords, wordsArray, permutations, i, this.NumberOfCharacters); phraseSet.FillPhraseSet(initialPhraseSet, this.AllWords, wordsArray, permutations, i);
action(phraseSet); action(phraseSet);
} }
} }

Loading…
Cancel
Save