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

Environment optimization #1035

Merged
merged 14 commits into from
Jan 12, 2024
Merged

Conversation

gabriel-barrett
Copy link
Contributor

This PR optimizes environments. Now, they're specialized data structures with its own tag Env. Empty environments are 0 valued environments, and otherwise they are a hash of size 4, the first element being the symbol payload, the second and third elements being the corresponding value's tag and payload, and the fourth element, the tail environment's payload. Doing this means lookups now take a single hash4, which allows us to do 8 lookups per step!

In the earlier PR, we simplified recursive envs by tagging symbols with a special tag to signal it came from a letrec. Now, because we don't have tags in symbols, some other strategy is needed. This is why I'm now tagging functions with a special recursive tag. It's important to note that this tag only appears in functions inside environment, as when you fetch them, it becomes a normal function with an extended environment. This is effectively the same behaviour as Lurk, although the internal representation is different

In earlier commits I gave another solution to letrecs which would solve issue #434 and actually give a proper letrec semantics, but the issue is that it would recompute recursive values and you'd end up with more iterations. This can only be solved with memoization, which will give the proper operational semantics to thunks, and can be solved after we've integrated the memoset into Lurk. Until then, we will have to settle on the other solution

@gabriel-barrett gabriel-barrett requested review from a team as code owners January 9, 2024 14:19
@gabriel-barrett gabriel-barrett requested a review from a team as a code owner January 9, 2024 15:57

// Allocate the image tag if it hasn't been allocated before,
// create the full image pointer and add it to bound allocations
let img_tag = ctx.global_allocator.alloc_tag_cloned(&mut cs, &Env);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this 'maybe' allocation deterministic within the circuit, or does it depend on the dynamic data? If the latter, then we risk inconsistent circuits. For this to be okay, the calls to alloc_tag_cloned need to always happen in the same order, with the same arguments. This is a larger question than just this usage.

I assume it's okay, since the design of the global allocator (and these lazy-allocating methods) assumes the above. I'm just mentioning so you can tell me it's fine everywhere. If in any doubt, we should convince ourselves.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe that all constants, including tags, are allocated before, so when you call this, it only amounts to getting the previously allocated constant. This does not depend on dynamic data, so it's fine

@porcuquine
Copy link
Contributor

!gpu-benchmark

@porcuquine
Copy link
Contributor

!gpu-bench

@gabriel-barrett
Copy link
Contributor Author

!gpu-benchmark

Copy link
Contributor

Benchmark for 73badc6

Click to view benchmark
Test Base PR %
LEM Fibonacci Prove - rc = 100/fib/num-100 1729.5±2.16ms 1742.8±2.50ms +0.77%
LEM Fibonacci Prove - rc = 100/fib/num-200 3.3±0.00s 3.4±0.00s +3.03%
LEM Fibonacci Prove - rc = 600/fib/num-100 1943.4±7.80ms 2.0±0.01s +2.91%
LEM Fibonacci Prove - rc = 600/fib/num-200 3.3±0.01s 3.4±0.00s +3.03%

porcuquine
porcuquine previously approved these changes Jan 11, 2024
Copy link
Contributor

@porcuquine porcuquine left a comment

Choose a reason for hiding this comment

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

Excellent. I'm obviously in favor of this change in principle. I looked at the code, and everything looks good. I would say that some LEM details are unfamiliar enough (have not stayed entirely up to speed on all internals) that having another set of eyes on the 'code review' rather than 'design review' would be useful.

@gabriel-barrett gabriel-barrett added this pull request to the merge queue Jan 11, 2024
@gabriel-barrett gabriel-barrett removed this pull request from the merge queue due to a manual request Jan 11, 2024
github-actions bot pushed a commit that referenced this pull request Jan 11, 2024
porcuquine
porcuquine previously approved these changes Jan 11, 2024
letrec will now add thunk expressions which adds themselves to the
environment before evaluating
This is so that we can delay hashing, much like `Ptr`s delay hashing
Now `letrec` works as before, but updated to the new, changed,
environment. The reason for reverting is that the iteration count
increased in a bunch of tests. For thunks to work properly, we will
need the memoset implementation of eval
@gabriel-barrett gabriel-barrett added this pull request to the merge queue Jan 12, 2024
github-actions bot pushed a commit that referenced this pull request Jan 12, 2024
Merged via the queue into lurk-lab:main with commit fa6d5c0 Jan 12, 2024
12 checks passed
@gabriel-barrett gabriel-barrett deleted the new-env branch January 12, 2024 00:58
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.

2 participants