-
Notifications
You must be signed in to change notification settings - Fork 152
Open
Description
When using Enzyme to differentiate through Eigen::Matrix<double, N, N>::inverse(), compilation fails at optimization level -O1, but succeeds at -O0, -O2, and -O3. Also the gradient value of using -O2 is different than the value of using -O0 and -O3.
Minimal reproducible example
#include <iostream>
#include <enzyme/enzyme>
#include <Eigen/Dense>
#include <vector>
#include <random>
int enzyme_dup;
int enzyme_dupnoneed;
int enzyme_out;
int enzyme_const;
template < typename return_type, typename ... T >
return_type __enzyme_fwddiff(void*, T ... );
template < typename return_type, typename ... T >
return_type __enzyme_autodiff(void*, T ... );
const size_t input_size = 2;
const size_t matrix_size = 3; // change to 2 or 3 works fine
using Matrix = Eigen::Matrix<double, matrix_size, matrix_size>;
void enzyme_func_matrix(Matrix* mats, double& sol){
Matrix M0;
M0 = mats[0].inverse();
sol = M0.sum();
}
template <auto F>
void compute_J_matrix_forward(std::vector<std::vector<std::vector<double>>> inputs, std::vector<std::vector<std::vector<double>>>& J_matrix_forward){
using Matrix = Eigen::Matrix<double, matrix_size, matrix_size>;
J_matrix_forward.assign(input_size,
std::vector<std::vector<double>>(
matrix_size,
std::vector<double>(matrix_size, 0.0)
)
);
std::vector<Matrix> mats(input_size), dmats(input_size);
for (size_t mat_idx = 0; mat_idx < input_size; mat_idx++){
for (size_t i = 0; i < matrix_size; i++){
for (size_t j = 0; j < matrix_size; j++){
mats[mat_idx](i, j) = inputs[mat_idx][i][j];
}
}
}
auto zero_gradients = [&]() {
for (auto& M : dmats) {
for (int i = 0; i < matrix_size; i++) {
for (int j = 0; j < matrix_size; j++) {
M(i, j)=0.0;
}
}
}
};
double result, dresult;
for (size_t mat_idx = 0; mat_idx < input_size; mat_idx++){
for (size_t i = 0; i < matrix_size; i++){
for (size_t j = 0; j < matrix_size; j++){
zero_gradients();
dmats[mat_idx](i, j) = 1.0;
__enzyme_fwddiff<void>((void*) F,
enzyme_dup, mats.data(), dmats.data(),
enzyme_dup, &result, &dresult);
J_matrix_forward[mat_idx][i][j] = dresult;
}
}
}
}
void generate_inputs(size_t matrix_size, std::vector<std::vector<std::vector<double>>>& inputs) {
inputs.assign(2,
std::vector<std::vector<double>>(
matrix_size,
std::vector<double>(matrix_size)
)
);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dist(0.0, 1.0);
for (auto& mat : inputs) {
for (auto& row : mat) {
for (auto& val : row) {
val = dist(gen);
}
}
}
}
int main() {
std::vector<std::vector<std::vector<double>>> J_matrix_forward;
std::vector<std::vector<std::vector<double>>> inputs;
generate_inputs(matrix_size, inputs);
compute_J_matrix_forward<enzyme_func_matrix>(inputs, J_matrix_forward);
size_t num_matrix_ele = input_size *matrix_size * matrix_size;
for (size_t input_idx = 0; input_idx < input_size; input_idx++){
for (size_t i = 0; i < matrix_size; i++){
for (size_t j = 0; j < matrix_size; j++){
std::cout << "J_matrix_forward[" << input_idx << "][" << i << "][" << j << "] = " << J_matrix_forward[input_idx][i][j] << std::endl;
}
}
}
return 0;
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels