Skip to content

perf: Use explicit squaring chain for the x^5 S-box - #59

Open
vadorovsky wants to merge 1 commit into
Lightprotocol:mainfrom
vadorovsky:vad/sbox
Open

vadorovsky wants to merge 1 commit into
Lightprotocol:mainfrom
vadorovsky:vad/sbox

Conversation

@vadorovsky

Copy link
Copy Markdown
Contributor

Field::pow is a generic binary exponentiation, costing 3 squarings + 2 multiplications for x^5. Replacing it with x^2 -> x^4 -> x^4 * x (2 squarings + 1 multiplication) speeds up hashing by up to ~47% for 1-2 inputs, degrading to ~2% at 12 inputs where the MDS dominates.

Benchmarked on AMD EPYC 7H12 64-core with the following results.

Before:

poseidon_bn254_x5_1     time:   [22.458 µs 22.501 µs 22.554 µs]
poseidon_bn254_x5_2     time:   [33.189 µs 33.391 µs 33.602 µs]
poseidon_bn254_x5_3     time:   [44.983 µs 45.054 µs 45.130 µs]
poseidon_bn254_x5_4     time:   [63.479 µs 63.533 µs 63.596 µs]
poseidon_bn254_x5_5     time:   [83.178 µs 83.214 µs 83.247 µs]
poseidon_bn254_x5_6     time:   [112.51 µs 112.81 µs 113.17 µs]
poseidon_bn254_x5_7     time:   [142.82 µs 143.19 µs 143.65 µs]
poseidon_bn254_x5_8     time:   [175.62 µs 176.55 µs 177.72 µs]
poseidon_bn254_x5_9     time:   [203.31 µs 203.36 µs 203.42 µs]
poseidon_bn254_x5_10    time:   [275.25 µs 276.37 µs 277.65 µs]
poseidon_bn254_x5_11    time:   [296.42 µs 296.77 µs 297.26 µs]
poseidon_bn254_x5_12    time:   [374.93 µs 375.45 µs 376.07 µs]

After:

poseidon_bn254_x5_1     time:   [15.333 µs 15.348 µs 15.367 µs]
poseidon_bn254_x5_2     time:   [24.189 µs 24.213 µs 24.244 µs]
poseidon_bn254_x5_3     time:   [35.364 µs 35.392 µs 35.427 µs]
poseidon_bn254_x5_4     time:   [53.129 µs 53.360 µs 53.639 µs]
poseidon_bn254_x5_5     time:   [71.739 µs 71.854 µs 71.995 µs]
poseidon_bn254_x5_6     time:   [98.231 µs 98.314 µs 98.407 µs]
poseidon_bn254_x5_7     time:   [128.92 µs 129.67 µs 130.74 µs]
poseidon_bn254_x5_8     time:   [163.55 µs 164.76 µs 166.04 µs]
poseidon_bn254_x5_9     time:   [190.60 µs 191.32 µs 192.08 µs]
poseidon_bn254_x5_10    time:   [256.79 µs 257.19 µs 257.65 µs]
poseidon_bn254_x5_11    time:   [282.91 µs 283.55 µs 284.33 µs]
poseidon_bn254_x5_12    time:   [367.30 µs 369.78 µs 372.52 µs]
inputs baseline sbox opt speedup
1 22.50 µs 15.35 µs 1.47×
2 33.39 µs 24.21 µs 1.38×
3 45.05 µs 35.39 µs 1.27×
4 63.53 µs 53.36 µs 1.19×
5 83.21 µs 71.85 µs 1.16×
6 112.81 µs 98.31 µs 1.15×
7 143.19 µs 129.67 µs 1.10×
8 176.55 µs 164.76 µs 1.07×
9 203.36 µs 191.32 µs 1.06×
10 276.37 µs 257.19 µs 1.07×
11 296.77 µs 283.55 µs 1.05×
12 375.45 µs 369.78 µs 1.02×

`Field::pow` is a generic binary exponentiation, costing 3 squarings +
2 multiplications for x^5. Replacing it with x^2 -> x^4 -> x^4 * x
(2 squarings + 1 multiplication) speeds up hashing by up to ~47% for
1-2 inputs, degrading to ~2% at 12 inputs where the MDS dominates.

Benchmarked on AMD EPYC 7H12 64-core with the following results.

Before:

```
poseidon_bn254_x5_1     time:   [22.458 µs 22.501 µs 22.554 µs]
poseidon_bn254_x5_2     time:   [33.189 µs 33.391 µs 33.602 µs]
poseidon_bn254_x5_3     time:   [44.983 µs 45.054 µs 45.130 µs]
poseidon_bn254_x5_4     time:   [63.479 µs 63.533 µs 63.596 µs]
poseidon_bn254_x5_5     time:   [83.178 µs 83.214 µs 83.247 µs]
poseidon_bn254_x5_6     time:   [112.51 µs 112.81 µs 113.17 µs]
poseidon_bn254_x5_7     time:   [142.82 µs 143.19 µs 143.65 µs]
poseidon_bn254_x5_8     time:   [175.62 µs 176.55 µs 177.72 µs]
poseidon_bn254_x5_9     time:   [203.31 µs 203.36 µs 203.42 µs]
poseidon_bn254_x5_10    time:   [275.25 µs 276.37 µs 277.65 µs]
poseidon_bn254_x5_11    time:   [296.42 µs 296.77 µs 297.26 µs]
poseidon_bn254_x5_12    time:   [374.93 µs 375.45 µs 376.07 µs]
```

After:

```
poseidon_bn254_x5_1     time:   [15.333 µs 15.348 µs 15.367 µs]
poseidon_bn254_x5_2     time:   [24.189 µs 24.213 µs 24.244 µs]
poseidon_bn254_x5_3     time:   [35.364 µs 35.392 µs 35.427 µs]
poseidon_bn254_x5_4     time:   [53.129 µs 53.360 µs 53.639 µs]
poseidon_bn254_x5_5     time:   [71.739 µs 71.854 µs 71.995 µs]
poseidon_bn254_x5_6     time:   [98.231 µs 98.314 µs 98.407 µs]
poseidon_bn254_x5_7     time:   [128.92 µs 129.67 µs 130.74 µs]
poseidon_bn254_x5_8     time:   [163.55 µs 164.76 µs 166.04 µs]
poseidon_bn254_x5_9     time:   [190.60 µs 191.32 µs 192.08 µs]
poseidon_bn254_x5_10    time:   [256.79 µs 257.19 µs 257.65 µs]
poseidon_bn254_x5_11    time:   [282.91 µs 283.55 µs 284.33 µs]
poseidon_bn254_x5_12    time:   [367.30 µs 369.78 µs 372.52 µs]
```

| inputs | baseline  | sbox opt  | speedup |
|--------|-----------|-----------|---------|
| 1      | 22.50 µs  | 15.35 µs  | 1.47×   |
| 2      | 33.39 µs  | 24.21 µs  | 1.38×   |
| 3      | 45.05 µs  | 35.39 µs  | 1.27×   |
| 4      | 63.53 µs  | 53.36 µs  | 1.19×   |
| 5      | 83.21 µs  | 71.85 µs  | 1.16×   |
| 6      | 112.81 µs | 98.31 µs  | 1.15×   |
| 7      | 143.19 µs | 129.67 µs | 1.10×   |
| 8      | 176.55 µs | 164.76 µs | 1.07×   |
| 9      | 203.36 µs | 191.32 µs | 1.06×   |
| 10     | 276.37 µs | 257.19 µs | 1.07×   |
| 11     | 296.77 µs | 283.55 µs | 1.05×   |
| 12     | 375.45 µs | 369.78 µs | 1.02×   |
@vadorovsky

Copy link
Copy Markdown
Contributor Author

I know that the same trick is done in #54, but I think it's better to keep one scoped optimization per PR instead of mixing them together. I'm planning to address performance of state, MDS etc. in a bit different way, and also get rid of vectors in all possible places.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant