Skip to content

Commit 1fc11b3

Browse files
authored
Bump version to v0.2.0
2 parents e17b128 + 96a3620 commit 1fc11b3

112 files changed

Lines changed: 1280 additions & 5747 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
.vscode
22
.DS_Store
33
target/
4-
vectors/
5-
graph.bin
64
**/*.metallib

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
# Existing Makefile content...
2-
31
# Clean target to remove .metal.lib and .metal.ir files
42
clean_ir:
53
find ./mopro-msm/src/msm/metal_msm/shader -type f \( -name "*.metal.lib" -o -name "*.metal.ir" \) -delete
64

75
.PHONY: clean
6+
7+
# Format MSL shaders using clang-format
8+
format_shaders:
9+
find mopro-msm/src/msm/metal_msm/shader -name "*.metal" -exec xcrun clang-format -i --style=WebKit {} \;
10+
.PHONY: format_shaders

README.md

Lines changed: 179 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,193 @@
1-
# mopro msm gpu-acceleration
1+
# Metal MSM
22

3-
We are researching and implementing methods to accelerate multi-scalar multiplication (MSM) on IOS mobile device.
3+
Metal-MSM v2 executes MSM on [BN254](https://hackmd.io/@jpw/bn254) curve on Apple GPUs using Metal Shading Language (MSL). Unlike v1, which naively split the work into smaller tasks, v2 takes [Tal and Koh’s WebGPU MSM](https://github.com/z-prize/2023-entries/tree/main/prize-2-msm-wasm/webgpu-only/tal-derei-koh-wei-jie) in ZPrize2023 and the cuZK [[LWY+23](https://eprint.iacr.org/2022/1321)] approach as reference.
44

5-
## mopro-msm
5+
By adopting sparse matrices, it improves the Pippenger algorithm [Pip76](https://dl.acm.org/doi/10.1109/SFCS.1976.21) with a more memory-efficient storage format and uses well-studied sparse matrix algorithms, such as sparse matrix–vector multiplication and sparse matrix transposition, in both the preprocessing phase (e.g., radix sort via sparse matrix transpose) and the bucket-accumulation phase to achieve high parallelism.
66

7-
This is a of various implementations of MSM functions, which are then integrated in `mopro-core`.
7+
We took the WebGPU MSM reference and tuned it for all scales by auto-adjusting workgroup sizes for each cuZK shaders with SIMD width and the amount of GPU cores, squeezing out better GPU utilization. Plus, with dynamic window sizes, we speed up small and medium inputs (2^14 – 2^18) by eliminating unused sparse-matrix columns.
88

9-
### Run benchmark on the laptop
10-
Currently we support these MSM algorithms on BN254:
11-
- arkworks_pippenger
12-
- bucket_wise_msm
13-
- precompute_msm
14-
- metal::msm (GPU)
9+
One thing to highlight is that our implementation runs most computations on the GPU, but it’s still slower than the CPU-only solution like [Arkworks](https://github.com/arkworks-rs). However, because we target client-side devices with limited resources, applying a hybrid approach, leveraging both CPU and GPU for MSM tasks and combining the results at the end, can yield an implementation slightly faster than a pure-CPU one. Check the write-up below for estimated speedups with this hybrid method.
1510

16-
Replace `MSM_ALGO` with one of the algorithms above to get the corresponding benchmarks.
11+
## How to use
1712

18-
Benchmarking for <u>single instance size</u>:
19-
```sh
20-
cargo test --release --package mopro-msm --lib -- msm::MSM_ALGO::tests::test_run_benchmark --exact --nocapture
13+
Metal MSM v2 works with `arkworks v0.4.x`; just include the crate in your `Cargo.toml`.
14+
```toml
15+
mopro-msm = { git = "https://github.com/zkmopro/gpu-acceleration.git", tag = "v0.2.0" }
2116
```
2217

23-
Benchmarking for <u>multiple instance size</u>:
24-
```sh
25-
cargo test --release --package mopro-msm --lib -- msm::MSM_ALGO::tests::test_run_multi_benchmarks --exact --nocapture
18+
Next, invoke MSM within your Rust code.
19+
```rust
20+
use mopro_msm::msm::metal_msm::{
21+
metal_variable_base_msm,
22+
test_utils::generate_random_bases_and_scalars, // optional
23+
};
24+
25+
fn main() {
26+
let input_size = 1 << 16;
27+
let (bases, scalars) = generate_random_bases_and_scalars(input_size);
28+
let msm_result = metal_variable_base_msm(&bases, &scalars);
29+
30+
println!("Result: {:?}", msm_result);
31+
}
2632
```
2733

28-
## gpu-exploration-app
34+
Because it’s compatible with Arkworks, you can seamlessly swap between Metal MSM and the Arkworks MSM implementation.
35+
```rust
36+
#[cfg(test)]
37+
mod tests {
38+
use super::*;
39+
use ark_bn254::{Fr as ScalarField, G1Projective as G};
40+
use ark_ec::{CurveGroup, VariableBaseMSM};
41+
use ark_std::{UniformRand, test_rng};
42+
43+
#[test]
44+
fn test_msm() {
45+
let input_size = 1 << 10;
2946

30-
This is a benchmark app to compare the performance of different algorithms on iOS device.
47+
// Generate random EC points and scalars with Arkworks
48+
let mut rng = test_rng();
49+
let bases = (0..input_size)
50+
.map(|_| G::rand(&mut rng).into_affine())
51+
.collect::<Vec<_>>();
52+
let scalars = (0..input_size)
53+
.map(|_| ScalarField::rand(&mut rng))
54+
.collect::<Vec<_>>();
3155

32-
You can run the following commands in the root directory of the project to compile the metal library for a given OS:
33-
```sh
34-
# for macOS
35-
bash mopro-msm/src/msm/metal/compile_metal.sh
56+
let metal_msm_result = metal_variable_base_msm(&bases, &scalars).unwrap();
57+
let arkworks_msm_result = G::msm(&bases, &scalars).unwrap();
3658

37-
# for iphoneOS
38-
bash mopro-msm/src/msm/metal/compile_metal_iphone.sh
59+
assert_eq!(metal_msm_result, arkworks_msm_result); // the result is the same
60+
}
61+
}
3962
```
63+
64+
## Benchmark
65+
66+
Benchmarking on BN254 curve ran on a MacBook Air with M3 chips, with test case setup time excluded.
67+
68+
<table>
69+
<thead>
70+
<tr>
71+
<th rowspan="2" style="text-align:center">Scheme</th>
72+
<th colspan="7" style="text-align:center">Input Size (ms)</th>
73+
</tr>
74+
<tr>
75+
<th style="text-align:center">2<sup>12</sup></th>
76+
<th style="text-align:center">2<sup>14</sup></th>
77+
<th style="text-align:center">2<sup>16</sup></th>
78+
<th style="text-align:center">2<sup>18</sup></th>
79+
<th style="text-align:center">2<sup>20</sup></th>
80+
<th style="text-align:center">2<sup>22</sup></th>
81+
<th style="text-align:center">2<sup>24</sup></th>
82+
</tr>
83+
</thead>
84+
<tbody style="text-align:center">
85+
<tr>
86+
<th style="text-align:center"><a href="https://github.com/arkworks-rs">Arkworks v0.4.x</a><br>(CPU, Baseline)</br></th>
87+
<td>6</td>
88+
<td>19</td>
89+
<td>69</td>
90+
<td>245</td>
91+
<td>942</td>
92+
<td>3,319</td>
93+
<td>14,061</td>
94+
</tr>
95+
<tr>
96+
<th style="text-align:center"><a href="https://github.com/zkmopro/gpu-acceleration/tree/v0.1.0">Metal MSM v0.1.0</a><br>(GPU)</br></th>
97+
<td>143<br>(-23.8x)</br></td>
98+
<td>273<br>(-14.4x)</br></td>
99+
<td>1,730<br>(-25.1x)</br></td>
100+
<td>10,277<br>(-41.9x)</br></td>
101+
<td>41,019<br>(-43.5x)</br></td>
102+
<td>555,877<br>(-167.5x)</br></td>
103+
<td>N/A</td>
104+
</tr>
105+
<tr>
106+
<th style="text-align:center"><a href="https://github.com/zkmopro/gpu-acceleration/tree/v0.2.0">Metal MSM v0.2.0</a><br>(GPU)</br></th>
107+
<td>134<br>(-22.3x)</br></td>
108+
<td>124<br>(-6.5x)</br></td>
109+
<td>253<br>(-3.7x)</br></td>
110+
<td>678<br>(-2.8x)</br></td>
111+
<td>1,702<br>(-1.8x)</br></td>
112+
<td>5,390<br>(-1.6x)</br></td>
113+
<td>22,241<br>(-1.6x)</br></td>
114+
</tr>
115+
<tr>
116+
<th style="text-align:center"><a href="https://github.com/ICME-Lab/msm-webgpu">ICME WebGPU MSM</a><br>(GPU)</br></th>
117+
<td>N/A</td>
118+
<td>N/A</td>
119+
<td>2,719<br>(-39.4x)</br></td>
120+
<td>5,418<br>(-22.1x)</br></td>
121+
<td>17,475<br>(-18.6x)</br></td>
122+
<td>N/A</td>
123+
<td>N/A</td>
124+
</tr>
125+
<tr>
126+
<th style="text-align:center"><a href="https://github.com/moven0831/icicle/tree/bn254-metal-benchmark">ICICLE-Metal v3.8.0</a><br>(GPU)</br></th>
127+
<td>59<br>(-9.8x)</br></td>
128+
<td>54<br>(-2.8x)</br></td>
129+
<td>89<br>(-1.3x)</br></td>
130+
<td>149<br>(+1.6x)</br></td>
131+
<td>421<br>(+2.2x)</br></td>
132+
<td>1,288<br>(+2.6x)</br></td>
133+
<td>4,945<br>(+2.8x)</br></td>
134+
</tr>
135+
</tbody>
136+
</table>
137+
138+
> side note:
139+
> - for ICME WebGPU MSM, input size 2^12 causes M3 chip machines to crash; any sizes not listed on the project’s GitHub page are shown as "N/A"
140+
> - for Metal MSM v0.1.0, the 2^24 benchmark was abandoned because it exceeded practical runtime
141+
142+
## Profiling summary (v1 vs v2)
143+
144+
Environment: M1 Pro, macOS 15.2, curve `ark_bn254`, dataset 2^20 unless stated. Medians of 5 runs.
145+
146+
### v2 → v1
147+
148+
| metric | v1[^1] | v2[^2] | gain |
149+
|---|---|---|---|
150+
| end-to-end latency | 10.3 s | **0.42 s** | **×24** |
151+
| GPU occupancy | 32 % | 76 % | +44 pp |
152+
| CPU share | 19 % | **<3 %** | –16 pp |
153+
| peak VRAM | 1.6 GB | **220 MB** | –7.3× |
154+
155+
Key changes:
156+
157+
* single sparse-matrix kernel eliminates most launches and memory thrash
158+
* CSR buckets keep data on-device → near-zero host↔GPU traffic
159+
* on-GPU radix sort makes preprocessing parallel
160+
161+
## Future
162+
163+
### Technical Improvements
164+
- **Modern Dependencies**: Update to `objc2` and `objc2-metal` ([objc2](https://github.com/madsmtm/objc2))
165+
- **Metal 4**: Adopt latest [Metal 4](https://developer.apple.com/metal/whats-new/) features
166+
- **Refactor with SIMD in mind**:
167+
- Instruction-level parallelism using vector types for faster FMA within SIMD groups
168+
- Memory coalescing to increase locality (e.g., structure of array instead of array of structure)
169+
- Optimized input reading patterns (e.g. `[X_i || Y_i]_0^{n-1}` instead of separate arrays)
170+
- Latency hiding and occupancy fine-tuning
171+
- Minimize thread divergence
172+
173+
### Algorithm & Integration
174+
- **CPU-GPU Hybrid**: Research interleaving with CPU MSM crate and update to `arkworks 0.5`
175+
- **Advanced Algorithms**:
176+
- Elastic MSM [[ZHY+24](https://eprint.iacr.org/2024/057.pdf)] implementation
177+
- Faster modular reduction with LogJump ([article by Wei Jie](https://kohweijie.com/articles/25/logjumps.html), [Barret-Montgomery](https://hackmd.io/@Ingonyama/Barret-Montgomery))
178+
179+
### Platform Expansion
180+
- **Cross-platform**: WGSL support with native execution environment
181+
- **Crypto Math Library**: Maintain a Metal/WebGPU crypto math library
182+
183+
## Community
184+
185+
- X account: <a href="https://twitter.com/zkmopro"><img src="https://img.shields.io/twitter/follow/zkmopro?style=flat-square&logo=x&label=zkmopro"></a>
186+
- Telegram group: <a href="https://t.me/zkmopro"><img src="https://img.shields.io/badge/telegram-@zkmopro-blue.svg?style=flat-square&logo=telegram"></a>
187+
188+
## Acknowledgements
189+
190+
This work was initially sponsored by a joint grant from [PSE](https://pse.dev/) and [0xPARC](https://0xparc.org/). It is currently incubated by PSE.
191+
192+
[^1]: https://hackmd.io/@yaroslav-ya/rJkpqc_Nke
193+
[^2]: https://hackmd.io/@yaroslav-ya/HyFA7XAQll

example-app/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)