Comments (5)
Hi @maxaehle
Thank you for opening the issue. The behaviour is expected and I am not sure if it's something that we would want to change in the near future. We should definitely report a proper warning/note if a global variable is used within a function being differentiated.
This behaviour is okay because most mathematical functions are pure functions and do not rely on global variables. It's also very difficult to obtain correct and consistent derivatives when global variables are involved because we cannot make any assumption on their initial values.
from clad.
Why we can't support that?
from clad.
Why we can't support that?
We can support it if we want to. However, it would be non-trivial and require effective usage of global tapes. For instance, please consider this example:
double global_var = 7;
double modify_global_var(double u) {
global_var += u;
}
double fn(double u, double v) {
global_var += v;
modify_global_var(u);
return global_var;
}
auto fn_grad = clad::gradient(fn);
To correctly differentiate the function fn
, we need to create an adjoint variable (_d_global_var
) for global_var
. But the issue is that it is unclear where to store _d_global_var
. We cannot store the adjoint _d_global_var
in the scope of fn_grad
because then the function calls inside fn_grad
would not be able to access _d_global_var
. We cannot create a global variable _d_global_var
because global variables come with their own sets of issues. One of them is, what if two functions that use global_var
are being differentiated. We will now need two global _d_global_var
for correctness reasons, but that is not possible.
We can use global tapes/vectors to support the correct differentiation of global variables, but this will be a considerable effort. So far, we treat global variables as constants due to these reasons.
from clad.
Thanks @parth-07 for your detailed analysis!
Just as a side info for triaging, this issue does not have to do with the HEP simulation I'm currently working on; I was only wondering how source-transformation AD deals with global variables.
Concerning whether support for global variables is desirable, my perspective is that it's good to support as much as of the language standard as possible. I agree that "ideal" use cases might be assumed to be written in a fully functional style without a global state. However, when adding AD functionality to an existing code written without AD in mind, global variables may easily be present.
Tapenade handles global variables, transforming
double g;
double f(double u){
g = u;
return g*g;
}
to
/* Generated by TAPENADE (INRIA, Ecuador team)
Tapenade 3.16 (bugfix_servletAD) - 4 Jan 2024 17:44
*/
#include <adStack.h>
double g;
double gb;
/*
Differentiation of f in reverse (adjoint) mode:
gradient of useful results: f
with respect to varying inputs: u
RW status of diff variables: g:(loc) f:in-killed u:out
*/
void f_b(double u, double *ub, double fb) {
g = u;
f = g*g;
gb = 2*g*fb;
*ub = gb;
}
so they introduce a global adjoint variable. I know to little about Clang/LLVM and Clad to see how complex it would be to do this in Clad.
So far I don't understand the issue that you think could arise when a global variable is accessed from several places. Local variables can be accessed multiple times (from within their scope) without problems. Does it help if we assume that only a single Clad evaluation like df.execute(...)
is running at a time (i.e. no multi-threading or nested Clad functions, don't know if such constructs are supported anyway)? And zero the adjoints of all globals in between any two Clad evaluations (if they're not automatically zeroed by the reverse evaluation)?
from clad.
Hi @maxaehle
Thank you for the detailed analysis!
so they introduce a global adjoint variable.
So tapenade uses global adjoint variables. I don't think it's a good solution. Using globals, in general, has issues. Using global adjoints has more issues on top of the general global issues. From the top of my head, there are two main issues:
-
Clad is also designed to be indirectly used. By indirect use, I mean users may not want to use Clad directly as a clang plugin. Instead, to use clad-generated derivatives in their projects, users can can separately use Clad to generate derivative codes, then copy the generated derivatives to their project source code and include necessary Clad header files. When used this way, users are not using Clad directly. As a side-effect, Clad cannot insert global adjoints. This situation is more complex in C++ than C because in C++, we can have deeply nested global / static variables as well. For large projects, user may himself not be aware of static / global variables and thus it would be difficut for users to manually add the adjoint variables in the project source code at the right places.
-
If we use the same global adjoint variable in different adjoint functions, then those adjoint functions will have undefined behavior if they are run concurrently.
Does it help if we assume that only a single Clad evaluation like df.execute(...) is running at a time
We cannot assume this and we should not.
(i.e. no multi-threading or nested Clad functions, don't know if such constructs are supported anyway)?
Running adjoint functions parallelly works and needs no support from Clad per se. For example:
auto d_fn1 = clad::gradient(fn1);
auto d_fn2 = clad::gradient(fn2);
// Execute d_fn1.execute(...) and d_fn2.execute(...) parallelly.
In the above example, Clad creates the adjoint functions and stores the function address in the objects d_fn1
and d_fn2
. Clad does not control or care about how users use these adjoint functions.
This all being said, thank you for opening the issue. We need to decide if we want to support global and static variables. There are ways to support them without the cons of using global adjoint variables. If we decide not to support them, then we should give a proper warning to users if the code being differentiated depends upon global / static variables.
Please let me know if you have any comments / questions.
from clad.
Related Issues (20)
- 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
- TBR analysis doesn't include the for loop's step in the forward pass when there's a statement inside with a body of its own HOT 7
- 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
- Non-compilable code output for division operation in reverse mode
- Incorrect gradient computation for non-zeroed derivatives HOT 4
- Regression in support of functions with unknown definition HOT 4
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.