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

Change gate evaluation memory layout #390

Merged
merged 1 commit into from
Dec 16, 2021
Merged

Conversation

nbgl
Copy link
Contributor

@nbgl nbgl commented Dec 7, 2021

This is the meat of the SIMD gate evaluation change. It changes the memory layouts associated with gate evaluation (inputs and outputs) to be matrices of field elements of shape [[F; num_points]; some_length].

It does not, by itself, enable SIMD evaluation. That PR will be easier and just a bunch of moving code around (without actually changing it much). I do not want these changes, which are more likely to be controversial, to be lost in that.

@nbgl nbgl changed the title WIP: Change gate evaluation memory layout Change gate evaluation memory layout Dec 7, 2021
@nbgl nbgl requested a review from dlubarov December 7, 2021 21:27
@nbgl nbgl mentioned this pull request Dec 7, 2021
src/gates/util.rs Outdated Show resolved Hide resolved
@dlubarov
Copy link
Contributor

Sorry for the delay, will try to review tomorrow

fn eval_unfiltered_base_one(
&self,
vars: EvaluationVarsBase<F>,
mut yield_constr: StridedConstraintConsumer<F>,
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: it seems a little unusual to me for an object name to be a verb, maybe call it something like a constraint buffer/consumer?

Copy link
Contributor

@dlubarov dlubarov Dec 16, 2021

Choose a reason for hiding this comment

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

(Not important though, feel free to disregard for now if it'd create conflicts)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a case where I thought clarity justified breaking convention. I was going for the feel of Python's generator syntax (yield statement).

yield_constr would ideally be a closure, except I wanted to add a many method for convenience when working with iterators. I can't make StridedConstraintConsumer callable without #![feature(fn_traits)], but functionally it's closer to a closure than to a struct: we don't care about the data it contains except as a means for interacting with our caller.

I also think that yield_constr.one is shorter and clearer than constraint_consumer.yield_one or similar.

}
}

pub trait Viewable<F> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems semantically similar to Index; could overloading Index with the range types work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this is supposed to be exactly like Index. Unfortunately, implementing Index does not work because Index::index returns a reference (index(&self, index: Idx) -> &Self::Output).

Now, in an ideal world PackedStridedView would be a reference. A slice is a reference where a pointer is augmented with extra metadata. Unfortunately, in a classic do-as-I-say-not-as-I-do Rust style, the maintainers have decided that the built-in fat pointer types are all that anyone should ever need and have not provided a way for the user to define custom ones.

So PackedStridedView is a struct and we need to return an instance of it. The instance does not exist until it is requested, so we can't return a reference as it would dangle. This precludes the use of Index and forces this ugly workaround.

Copy link
Contributor

@dlubarov dlubarov Dec 16, 2021

Choose a reason for hiding this comment

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

Oh I see. Please note in a brief comment. It seems like the plan is to add a IndexMove (rust-lang/rfcs/pull/2953) so there should eventually be a solution.

@dlubarov
Copy link
Contributor

General nit: I think the PhantomData::default()s can be shortened to PhantomData

// necessitates separate handling. It _could_ be done but it would also be uglier.
start_ptr: *const P::Scalar,
length: usize,
stride: usize, // This stride is in units of P::Scalar (NOT in bytes and NOT in P).
Copy link
Contributor

@dlubarov dlubarov Dec 16, 2021

Choose a reason for hiding this comment

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

nit: I think it's nice to make comments like this doc comments above the field, so IDEs associate them. Also please add a similar comment for the units of length

src/util/strided_view.rs Outdated Show resolved Hide resolved
stride
);

let start_ptr = data.as_ptr().wrapping_add(offset);
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you explain the use of wrapping_ methods in this PR? Is it to skip overflow checks as a debug mode optimization?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's needed to avoid UB in Rust's raw pointer handling. I'll add comments!

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've added some documentation. Let me know if it needs extra work 🙂

@dlubarov
Copy link
Contributor

General nit: I think &arr[..] is the same as &arr?

res
}

/// The result is an array of length vars_batch.len() * self.num_constraints(). Constraint j for
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: since these will eventually show up on docs.rs, I think it's nice to put code in backticks

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 went through the PR and inserted backticks where appropriate! There's a nonzero chance that I missed some though.

Copy link
Contributor

@dlubarov dlubarov left a comment

Choose a reason for hiding this comment

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

LGTM otherwise 👍

@nbgl nbgl merged commit eb7615f into main Dec 16, 2021
@nbgl nbgl deleted the jakub/gate-eval-mem-layout branch December 16, 2021 20:37
@nbgl nbgl mentioned this pull request Dec 20, 2021
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