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

For loops produce noncompilable code in the reverse mode #1078

Open
gojakuch opened this issue Sep 4, 2024 · 0 comments
Open

For loops produce noncompilable code in the reverse mode #1078

gojakuch opened this issue Sep 4, 2024 · 0 comments

Comments

@gojakuch
Copy link
Collaborator

gojakuch commented Sep 4, 2024

this might be a duplicate, for I think I've seen a similar issue, but I couldn't find it. anyway, here's the reproducer:

#include "clad/Differentiator/Differentiator.h"
#include "clad/Differentiator/STLBuiltins.h"
#include <iostream>

double fn(double x, double y) {
  std::vector<double> a;

  for (size_t i = 0; i < 5; ++i) {
    a.push_back((double)i);
    a[i] *= x;
  }

  return a[0];
}

int main(int argc, char* argv[]) {
    double dx, dy;
    auto df = clad::gradient(fn, "x, y");
    std::cout << fn(3, 4) << '\n';
    dx = 0; dy = 0;
    df.execute(3, 4, &dx, &dy);
    std::cout << dx << ' ' << dy << '\n';
}

Clad generates:

void fn_grad(double x, double y, double *_d_x, double *_d_y) {
    size_t _d_i = 0UL;
    size_t i = 0UL;
    clad::tape<std::vector<double> > _t1 = {};
    clad::tape<std::vector<double> > _t2 = {};
    clad::tape<double> _t4 = {};
    std::vector<double> _d_a({});
    std::vector<double> a;
    unsigned long _t0 = 0UL;
    for (i = 0; ; ++i) {
        {
            if (!(i < 5))
                break;
        }
        _t0++;
        clad::push(_t1, a);
        clad::custom_derivatives::class_functions::push_back_reverse_forw(&a, (double)i, &_d_a, _r0);
        clad::push(_t2, a);
        clad::ValueAndAdjoint<double &, double &> _t3 = clad::custom_derivatives::class_functions::operator_subscript_reverse_forw(&a, i, &_d_a, _r1);
        clad::push(_t4, _t3.value);
        _t3.value *= x;
    }
    std::vector<double> _t5 = a;
    clad::ValueAndAdjoint<double &, double &> _t6 = clad::custom_derivatives::class_functions::operator_subscript_reverse_forw(&a, 0, &_d_a, _r2);
    {
        std::vector::size_type _r2 = 0UL;
        clad::custom_derivatives::class_functions::operator_subscript_pullback(&_t5, 0, 1, &_d_a, &_r2);
    }
    for (;; _t0--) {
        {
            if (!_t0)
                break;
        }
        --i;
        {
            _t3.value = clad::pop(_t4);
            double _r_d0 = _t3.adjoint;
            _t3.adjoint = 0.;
            _t3.adjoint += _r_d0 * x;
            *_d_x += _t3.value * _r_d0;
            size_t _r1 = 0UL;
            clad::custom_derivatives::class_functions::operator_subscript_pullback(&clad::back(_t2), i, 0., &_d_a, &_r1);
            _d_i += _r1;
            clad::pop(_t2);
        }
        {
            double _r0 = 0.;
            clad::custom_derivatives::class_functions::push_back_pullback(&clad::back(_t1), (double)i, &_d_a, &_r0);
            _d_i += _r0;
            clad::pop(_t1);
        }
    }
}

of course, the produced code might change in Clad from time to time, but this is invalid C++ (for multiple reasons actually, but some of them are covered in other issues). this issue is about the following problem. on the line

clad::ValueAndAdjoint<double &, double &> _t3 = clad::custom_derivatives::class_functions::operator_subscript_reverse_forw(&a, i, &_d_a, _r1);

we save the result of the reverse_forw operation into the _t3 variable, which is created inside a for-loop. we then access this variable outside of this loop during the reverse pass later in the generated code. not only is this invalid C++, this is actually very hard to fix by manipulating the generated code manually, which is frustrating for the user.

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

No branches or pull requests

1 participant