-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize BigInteger.Divide #96895
base: main
Are you sure you want to change the base?
Optimize BigInteger.Divide #96895
Conversation
Tagging subscribers to this area: @dotnet/area-system-numerics Issue DetailsThe current Burnikel-Ziegler Algorithm is used in other languages.
|
27070b7
to
dd63906
Compare
There's a few different BigInteger PRs open right now, this is on my list to get to but I want to try and get some of the other ones completed/merged first |
dd63906
to
5079b54
Compare
1ac62fc
to
c72c0b6
Compare
Will this optimized Divide also result in a faster GreatestCommonDivisor method? I'm on the verge of rewriting a lot of C# code to Rust, only because of the BigInteger performance. |
@lskyum Just curious, what do you use big integer for? |
@danmoseley I'm using two BigInteger's to represent a "BigFraction", when performing various geometric calculations. |
@lskyum The division also affects a GCD method.
[GlobalSetup]
public void Setup()
{
o1 = OrigBigInteger.Pow(3, N) * OrigBigInteger.Pow(5, N);
o2 = OrigBigInteger.Pow(3, N) * OrigBigInteger.Pow(23, N);
m1 = MyBigInteger.Pow(3, N) * MyBigInteger.Pow(5, N);
m2 = MyBigInteger.Pow(3, N) * MyBigInteger.Pow(23, N);
} Environment: https://github.com/kzrnm/BigInteger/tree/main/Benchmark Benchmark code
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains.CsProj;
using MyBigInteger = Kzrnm.Numerics.BigInteger;
using OrigBigInteger = System.Numerics.BigInteger;
public class BenchmarkConfig : ManualConfig
{
static void Main(string[] args)
{
#if DEBUG
BenchmarkSwitcher.FromAssembly(typeof(BenchmarkConfig).Assembly).Run(args, new DebugInProcessConfig());
#else
_ = BenchmarkRunner.Run(typeof(BenchmarkConfig).Assembly);
#endif
}
public BenchmarkConfig()
{
AddExporter(BenchmarkDotNet.Exporters.MarkdownExporter.GitHub);
AddJob(Job.ShortRun.WithToolchain(CsProjCoreToolchain.NetCoreApp80));
SummaryStyle = SummaryStyle.Default
.WithRatioStyle(BenchmarkDotNet.Columns.RatioStyle.Value)
;
}
}
[Config(typeof(BenchmarkConfig))]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByParams)]
public class BigIntegerGcd
{
[Params(10000, 100000)]
public int N;
public OrigBigInteger o1, o2;
public MyBigInteger m1, m2;
[GlobalSetup]
public void Setup()
{
o1 = OrigBigInteger.Pow(3, N) * OrigBigInteger.Pow(5, N);
o2 = OrigBigInteger.Pow(3, N) * OrigBigInteger.Pow(23, N);
m1 = MyBigInteger.Pow(3, N) * MyBigInteger.Pow(5, N);
m2 = MyBigInteger.Pow(3, N) * MyBigInteger.Pow(23, N);
}
[Benchmark(Baseline = true)]
public OrigBigInteger Orig() => OrigBigInteger.GreatestCommonDivisor(o1, o2);
[Benchmark]
public MyBigInteger New() => MyBigInteger.GreatestCommonDivisor(m1, m2);
} |
@kzrnm That looks really awesome! Thanks for making this possible. |
Do we have enough coverage in dotnet/performance to protect this change? |
The 65536 bits correspond to a uint array of length 4096, which would cover this change. |
Can the problem be also hit in other unrelated tests that happen to use BigInteger.Divide? It seems that debug-only threshold overrides should be thread-local variable so that they do not affect other unrelated tests. |
Errors may occur in the following cases
|
# Conflicts: # src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.Utils.cs
The current$O(n^2)$ where n is the number of digits. The implementation of the pull request is implemented in Burnikel and Ziegler's Fast Recursive Division algorithm. It runs in $O(n^{\log 3} + n \log n)$ .
BigInteger.Divide
, which is implemented in the "grammar-school" algorithm, runs inBurnikel-Ziegler Algorithm is used in other languages.