Replies: 3 comments
-
|
The answer presently is "kind of" Enzyme presently supports annotations on individual parameters. This information is fed into Enzyme's activity analysis to deduce if any given instruction (such as a load/store) will impact the derivative computation or not. We could extend the representation to not just mark a value as inactive or not, but the value at a given pointer offset as inactive or not. This would allow what you describe (assuming your parameters are in arrays, if they're arguments you're good to go). Alternatively you might be able to get some of those benefits by making a wrapper function which itself has two arguments: one which is the inactive arguments (marked accordingly) and another which are the active args. Do you have a simple test case you can demonstrate this with? I'm specifically curious to see what potential performance boost you're hoping to see -- and how that compares with the added analysis code and time complexity. Alternatively, if its very few inputs, forward mode differentiation might be what you're looking for. The |
Beta Was this translation helpful? Give feedback.
-
|
Sorry for the late reply. I made a simple test case as follows. In this example, I split the parameters into two arrays and explicitly specified which one requires grad and which doesn't . #include <algorithm>
#include "timer.h"
using namespace std;
void __enzyme_autodiff(...);
int enzyme_dup, enzyme_const, enzyme_out, enzyme_dupnoneed;
double sum(double *x1, int size1,
double *x2, int size2)
{
double ret = 0.;
for (int j = 0; j < size1; j++)
ret += x1[j];
for (int j = 0; j < size2; j++)
ret += x2[j];
return ret;
}
void dsum1(double *x1, double *dx1, int size1,
double *x2, double *dx2, int size2)
{
__enzyme_autodiff((void *)(sum),
enzyme_dup, x1, dx1,
enzyme_const, size1,
enzyme_dup, x2, dx2,
enzyme_const, size2);
}
void dsum2(double *x1, double *dx1, int size1,
double *x2, int size2)
{
__enzyme_autodiff((void *)(sum),
enzyme_dup, x1, dx1,
enzyme_const, size1,
enzyme_const, x2,
enzyme_const, size2);
}
int main()
{
int size1 = 100;
int size2 = 100;
double x1[size1];
double dx1[size1];
double x1_const[size1];
std::fill_n(x1, size1, 1.);
std::fill_n(dx1, size1, 0.);
std::fill_n(x1_const, size1, 0.);
double x2[size2];
double dx2[size2];
double x2_const[size2];
std::fill_n(x2, size2, 1.);
std::fill_n(dx2, size2, 0.);
std::fill_n(x2_const, size2, 0.);
dsum1(x1, dx1, size1,
x2, dx2, size2);
dsum2(x1, dx1, size1,
x2, size2);
}I also tested the forward mode autodiff. It seems that the current version cannot handle the Eigen data types like Eigen::Vector. |
Beta Was this translation helpful? Give feedback.
-
|
@tgymnich re forward mode The other thing we could do, if the data structure is fixed is introduce a parameterized activity analysis (e.g. specify somewhere that at byte offsets 0, 8, and 16 the data is inactive, whereas it is active at 24). These would need to be known constants though. The other thing for this case in particular, is you might be able to use one parameter, and two for loops -- the second one with an |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi,
I'm trying to differentiate a function with millions of parameters with only a few parameters requiring grads. However, Enzyme would compute the gradients for all of them. I wondered whether it is necessary to explicitly specify which variables require grads to achieve better performance.
Beta Was this translation helpful? Give feedback.
All reactions