noir-optimize-acir

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ACIR Optimization Loop

ACIR优化循环

This workflow targets ACIR circuit size for constrained Noir programs. It does not apply to
unconstrained
(Brillig) functions — Brillig runs on a conventional VM where standard profiling and algorithmic improvements apply instead, and
bb gates
won't reflect Brillig performance.
本工作流针对受约束Noir程序的ACIR电路大小进行优化。它不适用于
unconstrained
(Brillig)函数——Brillig在传统虚拟机上运行,适用标准性能分析和算法改进,且
bb gates
无法反映Brillig的性能。

Measuring Circuit Size

测量电路大小

Binary projects

二进制项目

Compile the program and measure gate count with:
bash
nargo compile && bb gates -b ./target/<package>.json
编译程序并使用以下命令测量门数:
bash
nargo compile && bb gates -b ./target/<package>.json

Library projects

库项目

Libraries cannot be compiled with
nargo compile
. Instead, mark the functions you want to measure with
#[export]
and use
nargo export
:
bash
nargo export && bb gates -b ./export/<function_name>.json
Artifacts are written to the
export/
directory and named after the exported function (not the package).

If
bb
is not available, ask the user for their backend's equivalent command. Other backends should have a similar CLI interface.
The output contains two fields:
  • circuit_size
    : the actual gate count after backend compilation. This determines proving time, which is generally the bottleneck.
  • acir_opcodes
    : number of ACIR operations. This affects execution time (witness generation). A change can reduce opcodes without affecting circuit size or vice versa — both matter, but prioritize
    circuit_size
    when they conflict.
Always record a baseline of both metrics before making changes.
库无法使用
nargo compile
编译。相反,为你要测量的函数添加
#[export]
标记,然后使用
nargo export
bash
nargo export && bb gates -b ./export/<function_name>.json
产物会被写入
export/
目录,文件名以导出的函数命名(而非包名)。

如果没有
bb
工具,请询问用户其后端对应的等效命令。其他后端应具备类似的CLI界面。
输出包含两个字段:
  • circuit_size
    :后端编译后的实际门数。这决定了证明时间,通常是性能瓶颈。
  • acir_opcodes
    :ACIR操作的数量。这会影响执行时间(见证生成)。优化可能减少操作码但不影响电路大小,反之亦然——两者都很重要,但当两者冲突时,优先考虑
    circuit_size
在进行修改前,务必记录这两个指标的基准值。

Optimization Loop

优化循环

  1. Baseline: compile and record
    circuit_size
    .
  2. Apply one change at a time.
  3. Recompile and measure: compare
    circuit_size
    to the baseline.
  4. Revert if worse: if
    circuit_size
    increased or stayed the same, undo the change. Not every "optimization" helps — the compiler may already handle it, or the overhead of the new approach may outweigh the savings.
  5. Repeat from step 2 with the next candidate change.
  1. 基准测试:编译并记录
    circuit_size
  2. 每次仅应用一项修改
  3. 重新编译并测量:将
    circuit_size
    与基准值比较。
  4. 如果效果变差则回滚:如果
    circuit_size
    增加或保持不变,撤销修改。并非所有"优化"都有效——编译器可能已经处理了相关问题,或者新方法的开销超过了节省的成本。
  5. 重复:回到步骤2,进行下一项候选修改。

What to Try

可尝试的优化方法

Candidate optimizations roughly ordered by impact:
  • Hint and verify: replace expensive in-circuit computation with an unconstrained hint and constrained verification. This is the highest-impact optimization for most programs.
  • Reduce what you hint: if you're hinting intermediate values (selectors, masks, indices), see if you can hint only the final result and verify it directly.
  • Hoist assertions out of branches: replace
    if c { assert_eq(x, a) } else { assert_eq(x, b) }
    with
    assert_eq(x, if c { a } else { b })
    .
  • Simplify comparisons: inequality checks (
    <
    ,
    <=
    ) cost more than equality (
    ==
    ). But don't introduce extra state to avoid them — measure first.
候选优化方法按影响大致排序:
  • 提示与验证:将电路内的昂贵计算替换为无约束的提示和有约束的验证。这对大多数程序来说是影响最大的优化手段。
  • 减少提示内容:如果你正在提示中间值(选择器、掩码、索引),看看是否可以仅提示最终结果并直接验证。
  • 将断言提升到分支外:替换
    if c { assert_eq(x, a) } else { assert_eq(x, b) }
    assert_eq(x, if c { a } else { b })
  • 简化比较操作:不等式检查(
    <
    <=
    )的成本高于相等性检查(
    ==
    )。但不要为了避免它们而引入额外状态——先进行测量。

What Not to Try

不建议尝试的操作

  • Don't hint division or modular arithmetic: the compiler already injects unconstrained helpers for these.
  • Don't hand-roll conditional selects:
    if/else
    expressions compile to the same circuit as
    c * (a - b) + b
    .
  • Don't replace
    <=
    with flag tracking without measuring
    : adding mutable state across loop iterations can produce more gates than a simple comparison.
  • 不要对除法或模运算使用提示:编译器已经为这些操作注入了无约束的辅助函数。
  • 不要手动实现条件选择
    if/else
    表达式编译后的电路与
    c * (a - b) + b
    相同。
  • 不要在未测量的情况下用标志跟踪替换
    <=
    :在循环迭代中添加可变状态可能会比简单的比较产生更多的门。