juno icon indicating copy to clipboard operation
juno copied to clipboard

Optimize the DivMod function

Open joshklop opened this issue 2 years ago • 1 comments

The divMod function in points.go is a major bottleneck when applying state diffs to the local database. Right now, we are using big.Ints, which are inefficient.

Solution

An implementation of Lehmer's GCD algorithm using the felt package. This is the same algorithm that the big package uses, but our felt.Felts should vastly outperform big.Ints.

Note that we don't want to use the modular arithmetic functions provided by the felt package when computing the GCD. Since our felts are just [4]uint64 underneath, we can use the very fast uint256 library instead.

Alternatives Considered

I have tried to implement this using gmp.Int as a drop-in replacement for big.Int, but it was slower than using big.Ints directly (probably due to the increase in allocations from felt -> big.Int -> gmp.Int -> big.Int -> felt).

I also considered porting the igcdex function from the Python reference implementation, but it implements Euclid's GCD algorithm, which is slower than Lehmer's algorithm for big numbers.

joshklop avatar Jul 05 '22 19:07 joshklop

some of the discussions we had on this -

  1. The Inverse function provided by the felt package doesn't work as a replacement for Lehmer's gcd function to compute inverses, since it computes the results modulo p, which changes the results of the product
  2. The problem with implementing Lehmer's gcd for felts is that we still need a way to handle negative values with felts. Maybe, this can be achieved by using a new variable to keep track of the felt's sign whenever it under/over flows.

ayushm2003 avatar Aug 24 '22 19:08 ayushm2003