Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster no-cython implementation of code distance #248

Open
perlinm opened this issue Feb 28, 2025 · 4 comments
Open

Faster no-cython implementation of code distance #248

perlinm opened this issue Feb 28, 2025 · 4 comments

Comments

@perlinm
Copy link
Collaborator

perlinm commented Feb 28, 2025

See comment by @richrines1.

In the process of adding the implementation above, we should make sure to include:

  1. a version for classical codes,
  2. a version for quantum CSS codes (with logical ops and stabilizers being n-bit strings for an n-qubit code), and
  3. a version for non-CSS codes (operators = 2n-bit strings, and weight = symplectic weight).

We may as well also use the popcnt instruction from numpy>=2.0.0. I'm willing to push stim/sinter to push a new release that unblocks numpy>=2.0.0 🙂

@perlinm
Copy link
Collaborator Author

perlinm commented Feb 28, 2025

Stray thought: the pure-numpy implementation above is not really an apples-to-apples comparison with the cython code, because it has extra batching that might make it faster. It might be worth making an apples-to-apples comparison to see whether one of these implementations is significantly faster.

Having said that, any implementation that is faster (and not significantly more complex) than the current implementation is worth merging. So the comparison can be left "for future work".

@perlinm
Copy link
Collaborator Author

perlinm commented Feb 28, 2025

@richrines1 you want to take credit by opening a draft PR your implementation?

@richrines1
Copy link
Contributor

Hmm, I think that makes sense.

I think we can just use the code inside the else block, right? The for ll in range(1, 2 ** len(int_logical_ops)) loop will be empty because if initially block_size <= len(int_logical_ops), then after setting int_logical_ops[block_size:] we'll be left with len(int_logical_ops) == 0.

UPDATE: nvm I missed the fill out block with products of some stabilizers part. So maybe it's still worth being clever.

UPDATE 2: oh but we could maybe initially do something like

blocked = np.zeros((1, int_logical_ops.shape[-1]), dtype=dtype)
for op in int_logical_ops[:block_size]:
blocked = np.vstack([blocked, blocked ^ op])

for op in int_stabilizers[: block_size - len(int_logical_ops)]:
blocked = np.vstack([blocked, blocked ^ op])

stabilizers = stabilizers[min(block_size - len(int_logical_ops), 0) :]
int_logical_ops = int_logical_ops[block_size:]

but I need to think more carefully about how to avoid the logical identity operator...

In any case, let's move this discussion to #248

yeah there's almost definitely a clever way to unify the two paths cleanly - it's just somewhat tricky to get right so splitting it up made it easier to prototype. will think about it a bit more and then open a pr :)

@richrines1
Copy link
Contributor

btw just tried this with numpy 2.1 - brought it down to ~8s for ToricCode(8)

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

No branches or pull requests

2 participants