Comments (7)
The code looks good to me. Could you explain what concerns you in particular? How should the for loop's step be included?
from clad.
Yes, here the result is not compromised, but if it depended on the value of i (e.g. val += i) then it would be wrong. Hence, the increment of i should be included similarly to the case where TBR is not enabled.
from clad.
Do you mean --i
in the reverse pass? It's not included because we don't need the value of i
. It is the purpose of TBR analysis to detect what values we don't need to restore to compute the derivatives. Adding val += i
would not change anything because the transformation is linear. However, if we differentiate a function where the value of i
is necessary, we will still have --i
. e.g.
double f(double val) {
for (int i=1; i<5; ++i) {
val += val * i;
}
return val;
}
gives us
void f_grad(double val, double *_d_val) {
unsigned long _t0;
int _d_i = 0;
int i = 0;
clad::tape<double> _t1 = {};
_t0 = 0;
for (i = 1; i < 5; ++i) {
_t0++;
clad::push(_t1, val);
val += val * i;
}
goto _label0;
_label0:
*_d_val += 1;
for (; _t0; _t0--) {
--i;
{
val = clad::pop(_t1);
double _r_d0 = *_d_val;
*_d_val += _r_d0 * i;
_d_i += val * _r_d0;
}
}
}
where we see both i
and val
be stored and restored because we need them to compute the derivatives.
from clad.
Agreed, but when there's an if or a switch statement or generally a statement with a body, its body isn't traversed I suppose and hence the increment is not included.
double fn21(double val) {
double res = 0;
for (int i=1; i<5; ++i) {
if (i == 3)
continue;
res += i * val;
}
return res;
}
- With TBR:
void fn21_grad(double val, double *_d_val) {
double _d_res = 0;
unsigned long _t0;
int _d_i = 0;
int i = 0;
clad::tape<bool> _t2 = {};
clad::tape<unsigned long> _t3 = {};
double res = 0;
_t0 = 0;
for (i = 1; i < 5; ++i) {
_t0++;
bool _t1 = i == 3;
{
if (_t1) {
clad::push(_t3, 1UL);
continue;
}
clad::push(_t2, _t1);
}
res += i * val;
clad::push(_t3, 2UL);
}
goto _label0;
_label0:
_d_res += 1;
for (; _t0; _t0--)
switch (clad::pop(_t3)) {
case 2UL:
;
{
double _r_d0 = _d_res;
_d_i += _r_d0 * val;
*_d_val += i * _r_d0;
}
if (clad::pop(_t2))
case 1UL:
;
}
}
Without TBR:
void fn21_grad(double val, double *_d_val) {
double _d_res = 0;
unsigned long _t0;
int _d_i = 0;
int i = 0;
clad::tape<bool> _t2 = {};
clad::tape<unsigned long> _t3 = {};
clad::tape<double> _t4 = {};
double res = 0;
_t0 = 0;
for (i = 1; i < 5; ++i) {
_t0++;
bool _t1 = i == 3;
{
if (_t1) {
clad::push(_t3, 1UL);
continue;
}
clad::push(_t2, _t1);
}
clad::push(_t4, res);
res += i * val;
clad::push(_t3, 2UL);
}
goto _label0;
_label0:
_d_res += 1;
for (; _t0; _t0--) {
--i;
switch (clad::pop(_t3)) {
case 2UL:
;
{
res = clad::pop(_t4);
double _r_d0 = _d_res;
_d_i += _r_d0 * val;
*_d_val += i * _r_d0;
}
if (clad::pop(_t2))
case 1UL:
;
}
}
}
I will update the issue title as this case was the one that made me open the issue in the first place.
from clad.
Okay, this is definitely a bug. I will need more time to find out why this happens. Thank you for pointing this out.
from clad.
@kchristin22, do you mind looking in the tbr analysis and try to pinpoint the underlying problem? Petro is overloaded with other things in the next couple of weeks.
from clad.
Unfortunately my schedule is also pretty packed these weeks. I'll try to have a look if possible.
from clad.
Related Issues (20)
- Add user-interface for generating pushforward functions
- Using std::array inside functions to be differentiated? HOT 3
- Support for std::initializer_list HOT 1
- Consider a redesign of the for loop's body in reverse pass
- Enable remaining XFAIL tests on i586
- Incorrect derivative result when recursive function is used HOT 3
- Support for differentiating constructors in the forward mode AD
- Support for static_asserts in primal functions.
- Don't increment the for loop variable when there's a break statement HOT 1
- Python based build script to cover both Windows and Unix systems HOT 2
- Add tests for clang-repl HOT 1
- Avoid access of plugin methods from Visitors HOT 1
- Error in gradients for `if conditions` with declarations
- Move backward incompatible changes for v2.0 HOT 1
- Remove the assert on AppendDelayed
- Custom derivatives are not detected and used correctly when namespaces are present.
- Add custom derivatives for all math and other std:: builtin functions
- Add a target for verifying only `CHECK-EXEC` in tests
- Missing derivative with globals / variables of static storage duration HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from clad.