Skip to content

Add lightweight prove path and hint-free LogUp API #203

Open
hczphn wants to merge 1 commit intomasterfrom
hc/export_device_memories_unchecked
Open

Add lightweight prove path and hint-free LogUp API #203
hczphn wants to merge 1 commit intomasterfrom
hc/export_device_memories_unchecked

Conversation

@hczphn
Copy link
Collaborator

@hczphn hczphn commented Feb 21, 2026

Summary

  • Add export_device_memories_unchecked() to Context — exports device memories without the WitnessDone state assertion, keeping the original export_device_memories() unchanged and fully backward-compatible.
  • Add prove_lightweight() to ExpanderNoOverSubscribe — allows proving with only device_memories, without holding
    computation_graph or prover_setup references. This enables callers to release large data structures before the prove phase to reduce peak memory.
  • Add final_check_with_query_count() to LogUpSingleKeyTable and LogUpRangeProofTable — supports hint-free logup verification with externally provided query counts.
  • Support ZKML_NUM_CPUS environment variable to override physical CPU detection for MPI process count.

Motivation

Related: #202

For workloads without padding and without hint functions, the current prove path (copy_to_devicecall_kernel
solve_witnessexport_device_memoriesprove) introduces significant overhead from call_kernel (redundant hashing, unnecessary eval_safe_simd) and solve_witness.

With export_device_memories_unchecked() + prove_lightweight(), callers can bypass call_kernel and solve_witness entirely: just copy_to_deviceexport_device_memories_uncheckedprove_lightweight. This is only applicable when no padding or hint functions are needed.

…t prove, and configurable CPU count

- Add `export_device_memories_unchecked()` for exporting device memories without
  state assertion, enabling memory optimization workflows where context is dropped
  before proving
- Add `prove_lightweight()` to ExpanderNoOverSubscribe, allowing prove without
  holding computation_graph or prover_setup references
- Add `final_check_with_query_count()` to LogUpSingleKeyTable and
  LogUpRangeProofTable for hint-free logup verification with externally provided
  query counts
- Support `ZKML_NUM_CPUS` env var to override physical CPU detection for MPI
  process count

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @hczphn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces several optimizations aimed at improving the efficiency and memory footprint of the proving process, particularly for workloads without padding or hint functions. It provides new APIs to bypass redundant computation steps and allows for more flexible memory management by enabling the release of large data structures earlier in the proving pipeline. Additionally, it enhances configuration flexibility for parallel execution by allowing manual override of CPU detection.

Highlights

  • Unchecked Device Memory Export: Introduced export_device_memories_unchecked() to Context for exporting device memories without WitnessDone state assertion, maintaining backward compatibility for the original export_device_memories().
  • Lightweight Proving: Added prove_lightweight() to ExpanderNoOverSubscribe, enabling proving using only device_memories and allowing release of large data structures like computation_graph and prover_setup to reduce peak memory.
  • Hint-Free LogUp Verification: Implemented final_check_with_query_count() in LogUpSingleKeyTable and LogUpRangeProofTable to support hint-free logup verification with externally provided query counts.
  • MPI Process Count Configuration: Added support for the ZKML_NUM_CPUS environment variable to override physical CPU detection for determining the MPI process count.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • circuit-std-rs/src/logup.rs
    • Added final_check_with_query_count to LogUpSingleKeyTable for hint-free logup verification.
    • Added final_check_with_query_count to LogUpRangeProofTable for hint-free logup verification.
  • expander_compiler/src/zkcuda/context.rs
    • Introduced export_device_memories_unchecked to export memories without state checks.
    • Refactored export_device_memories to use a new private helper export_device_memories_impl.
  • expander_compiler/src/zkcuda/proving_system/expander_no_oversubscribe/api_no_oversubscribe.rs
    • Added prove_lightweight function to enable proving with only device memories.
  • expander_compiler/src/zkcuda/proving_system/expander_parallelized/client_utils.rs
    • Updated MPI size calculation to respect the ZKML_NUM_CPUS environment variable.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces several useful features for optimizing the proving process, including a lightweight prove path and hint-free LogUp API. The addition of export_device_memories_unchecked() and prove_lightweight() provides flexibility for memory management. The support for ZKML_NUM_CPUS environment variable is a good enhancement for controlling parallel execution. One area for improvement is the error handling in LogUpSingleKeyTable::final_check_with_query_count.

Comment on lines +337 to +338
if self.table.is_empty() || self.query_keys.is_empty() {
panic!("empty table or empty query");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using panic! for empty table or query inputs can lead to an abrupt program termination. Consider returning a Result type to allow callers to handle this error gracefully, or at least logging a more informative error before panicking, especially in a library context where consumers might expect more robust error handling.

Suggested change
if self.table.is_empty() || self.query_keys.is_empty() {
panic!("empty table or empty query");
if self.table.is_empty() || self.query_keys.is_empty() {
// TODO: Consider returning a Result<_, Error> instead of panicking
// or logging a more specific error message.
panic!("empty table or empty query");
}

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