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

RFC: Allow computations to semantically be evaluated when compute is invoked #478

Open
stephenchouca opened this issue Jun 28, 2021 · 1 comment
Labels

Comments

@stephenchouca
Copy link
Contributor

stephenchouca commented Jun 28, 2021

Motivation

Currently, the semantics of the C++ library is such that, from the user's perspective, computations always appear as if they are evaluated at the point of assignment:

Tensor<double> a, b;

a(0) = 1.0;
a(1) = 2.0;
b = a(i);
std::cout << b << std::endl;  // Prints out 3

a(2) = 3.0;
std::cout << b << std::endl;  // Still prints out 3, since `a` is modified after `b` has already been assigned

This makes sense when a user is relying on the lazy evaluation mechanism to trigger computations. However, this is not as intuitive when computations are triggered by explicitly invoking evaluate (or assemble and compute), since users tend to expect that the computation will actually be (re)performed whenever evaluate is invoked:

Tensor<double> a, b;

a(0) = 1.0;
a(1) = 2.0;
b = a(i);
b.evaluate();
std::cout << b << std::endl;  // Prints out 3

a(2) = 3.0;
b.evaluate();
std::cout << b << std::endl;  // Still prints out 3, since `a` is modified after `b` has already been assigned

Proposed Changes

This RFC proposes that users be able to specify whether computations should semantically happen at the point of assignment or whenever evaluate/assemble/compute is explicitly invoked. Specifically, the C++ library would expose a new global function:

void setEvaluateAtAssign(bool evalAtAssign);

which the user may invoke before any computation is defined. If setEvaluateAtAssign is invoked with the argument evalAtAssign being true, then any computation that is defined afterwards will appear as if it is evaluated at the point of assignment (i.e., as in the examples above). On the other hand, if setEvaluateAtAssign is invoked with the argument evalAtAssign being false, then any computation that is defined afterwards will be (re)performed whenever evaluate/assemble/compute is explicitly invoked:

Tensor<double> a, b;

setEvaluateAtAssign(false);

a(0) = 1.0;
a(1) = 2.0;
b = a(i);
b.evaluate();
std::cout << b << std::endl;  // Prints out 3

a(2) = 3.0;
b.evaluate();
std::cout << b << std::endl;  // Prints out 6

A prototype of this RFC is implemented in the eval_at_assign branch of the repo.

This feature can be particularly useful in, for instance, iterative applications where the structure of the output does not change (I believe this is the use case @stkaplan was interested in?):

Tensor<double> y, x, A;

y(i) = A(i,j) * x(j);
y.assemble();

while(...) {
  // Make some modifications to x...
  x.insert(...);

  // Recompute y with modified x
  y.compute();
}

As pointed out in #408, this feature can also be useful for benchmarking.

@stkaplan
Copy link
Contributor

That should work for my use case, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants