Small optimizations

This commit is contained in:
mlemanczyk committed 2025-10-16 19:46:25 +02:00
1 parent 07395830a5
commit aa4ff799f3
1 file changed
+43 -30
+43 -30
View File
@@ -793,10 +793,14 @@ internal static partial class PrimeOrderCalculator
} }
const int FactorSlotCount = GpuSmallPrimeFactorSlots; const int FactorSlotCount = GpuSmallPrimeFactorSlots;
ulong[] primeSlotsArray = ThreadStaticPools.UlongPool.Rent(FactorSlotCount);
int[] exponentSlotsArray = ThreadStaticPools.IntPool.Rent(FactorSlotCount); // stackalloc is faster than pooling
Span<ulong> primeSlots = primeSlotsArray.AsSpan(0, FactorSlotCount); // ulong[] primeSlotsArray = ThreadStaticPools.UlongPool.Rent(FactorSlotCount);
Span<int> exponentSlots = exponentSlotsArray.AsSpan(0, FactorSlotCount); // int[] exponentSlotsArray = ThreadStaticPools.IntPool.Rent(FactorSlotCount);
// Span<ulong> primeSlots = primeSlotsArray.AsSpan(0, FactorSlotCount);
// Span<int> exponentSlots = exponentSlotsArray.AsSpan(0, FactorSlotCount);
Span<ulong> primeSlots = stackalloc ulong[FactorSlotCount];
Span<int> exponentSlots = stackalloc int[FactorSlotCount];
// We don't need to worry about leftovers, because we always use indexes within the calculated counts // We don't need to worry about leftovers, because we always use indexes within the calculated counts
// primeSlots.Clear(); // primeSlots.Clear();
// exponentSlots.Clear(); // exponentSlots.Clear();
@@ -839,7 +843,7 @@ internal static partial class PrimeOrderCalculator
if (config.PollardRhoMilliseconds > 0 && pending.Count > 0) if (config.PollardRhoMilliseconds > 0 && pending.Count > 0)
{ {
long deadlineTimestamp = CreateDeadlineTimestamp(config.PollardRhoMilliseconds); long deadlineTimestamp = CreateDeadlineTimestamp(config.PollardRhoMilliseconds);
compositeStack = ThreadStaticPools.RentUlongStack(Math.Max(pending.Count * 2, 4)); compositeStack = ThreadStaticPools.RentUlongStack(Math.Max(pending.Count << 1, 4));
compositeStack.Push(remaining); compositeStack.Push(remaining);
pending.Clear(); pending.Clear();
@@ -847,10 +851,11 @@ internal static partial class PrimeOrderCalculator
while (compositeStack.Count > 0) while (compositeStack.Count > 0)
{ {
ulong composite = compositeStack.Pop(); ulong composite = compositeStack.Pop();
if (composite <= 1UL) // composite will never be smaller than 1 on the execution path
{ // if (composite <= 1UL)
continue; // {
} // continue;
// }
bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite); bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite);
if (isPrime) if (isPrime)
@@ -888,7 +893,9 @@ internal static partial class PrimeOrderCalculator
{ {
AddFactorToCollector(ref useDictionary, ref counts, primeSlots, exponentSlots, ref factorCount, composite, 1); AddFactorToCollector(ref useDictionary, ref counts, primeSlots, exponentSlots, ref factorCount, composite, 1);
} }
else if (composite > 1UL) // composite is never smaller on the execution path
// else if (composite > 1UL)
else
{ {
cofactor = checked(cofactor * composite); cofactor = checked(cofactor * composite);
} }
@@ -967,8 +974,8 @@ internal static partial class PrimeOrderCalculator
result = PartialFactorResult.Rent(array, cofactor, fullyFactoredArray, arrayIndex); result = PartialFactorResult.Rent(array, cofactor, fullyFactoredArray, arrayIndex);
ReturnResult: ReturnResult:
ThreadStaticPools.UlongPool.Return(primeSlotsArray); // ThreadStaticPools.UlongPool.Return(primeSlotsArray);
ThreadStaticPools.IntPool.Return(exponentSlotsArray); // ThreadStaticPools.IntPool.Return(exponentSlotsArray);
if (counts is not null) if (counts is not null)
{ {
@@ -1055,16 +1062,18 @@ internal static partial class PrimeOrderCalculator
factorCount = 0; factorCount = 0;
remaining = value; remaining = value;
if (value <= 1UL) // value will never <= 1 in production code
{ // if (value <= 1UL)
return true; // {
} // return true;
// }
int capacity = Math.Min(primeTargets.Length, exponentTargets.Length); int capacity = Math.Min(primeTargets.Length, exponentTargets.Length);
if (capacity == 0) // capacity will never equal 0 in production code
{ // if (capacity == 0)
return false; // {
} // return false;
// }
uint[] primes = PrimesGenerator.SmallPrimes; uint[] primes = PrimesGenerator.SmallPrimes;
ulong[] squares = PrimesGenerator.SmallPrimesPow2; ulong[] squares = PrimesGenerator.SmallPrimesPow2;
@@ -1086,16 +1095,18 @@ internal static partial class PrimeOrderCalculator
} }
ulong primeSquare = squares[i]; ulong primeSquare = squares[i];
if (primeSquare != 0UL && primeSquare > remainingLocal) // primeSquare will never == 0 in production code
// if (primeSquare != 0 && primeSquare > remainingLocal)
if (primeSquare > remainingLocal)
{ {
break; break;
} }
ulong primeValue = primeCandidate; // primeCandidate will never equal 0 in production code
if (primeValue == 0UL) // if (primeCandidate == 0UL)
{ // {
continue; // continue;
} // }
ref CycleRemainderStepper stepper = ref cycleSteppers[i]; ref CycleRemainderStepper stepper = ref cycleSteppers[i];
ulong remainder; ulong remainder;
@@ -1131,20 +1142,22 @@ internal static partial class PrimeOrderCalculator
{ {
continue; continue;
} }
// TODO: Can we calculate this using residue steppers? We can try reusing modulo calculation for division result or the other way around
int exponent = 0; int exponent = 0;
do do
{ {
remainingLocal /= primeValue; remainingLocal /= primeCandidate;
exponent++; exponent++;
} }
while ((remainingLocal % primeValue) == 0UL); while ((remainingLocal % primeCandidate) == 0UL);
if (factorCount >= capacity) if (factorCount >= capacity)
{ {
return false; throw new InvalidOperationException($"Capacity is smaller than factor count");
} }
primeTargets[factorCount] = primeValue; primeTargets[factorCount] = primeCandidate;
exponentTargets[factorCount] = exponent; exponentTargets[factorCount] = exponent;
factorCount++; factorCount++;
} }