vgvassilev / clad Goto Github PK
View Code? Open in Web Editor NEWclad -- automatic differentiation for C/C++
License: GNU Lesser General Public License v3.0
clad -- automatic differentiation for C/C++
License: GNU Lesser General Public License v3.0
Can be reproduced with:
int f(int x)
try { return x; }
catch(...) { return 0; }
...
clad::differentiate(f, 0);
Failing Tests (3):
clad :: FirstDerivative/TemplateFunction.C
clad :: Gradient/Gradients.C
clad :: Gradient/TestAgainstDiff.C
Expected Passes : 18
Expected Failures : 3
Unexpected Failures: 3
lldb -- /Users/vvassilev/workspace/builds/llvm-root-debug/obc/bin/clang-5.0 -cc1 -triple x86_64-apple-macosx10.12.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -main-file-name Gradients.C -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -masm-verbose -munwind-tables -faligned-alloc-unavailable -target-cpu penryn -target-linker-version 305 -dwarf-column-info -debugger-tuning=lldb -resource-dir /Users/vvassilev/workspace/builds/llvm-root-debug/obc/bin/../../../../../llvm-root-debug/lib/clang/5.0.0/ -I /Users/vvassilev/workspace/sources/root-llvm/tools/clad/test/Gradient/../../include -stdlib=libc++ -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /Users/vvassilev/workspace/builds/llvm-root-debug/obc -ferror-limit 19 -fmessage-length 117 -stack-protector 1 -fblocks -fobjc-runtime=macosx-10.12.0 -fencode-extended-block-signature -fcxx-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -add-plugin clad -plugin-arg-clad -fdump-derived-fn -load /Users/vvassilev/workspace/builds/llvm-root-debug/obc/./lib/clad.dylib -o /var/folders/cp/g4fhftbd5c3fsp08mc8nr1pr0000gn/T/Gradients-848bce.o -x c++ /Users/vvassilev/workspace/sources/root-llvm/tools/clad/test/Gradient/Gradients.C
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
❲ 0❳ __pthread_kill ❮libsystem_kernel.dylib❯
❲ 1❳ pthread_kill ❮libsystem_pthread.dylib❯
❲ 2❳ abort ❮libsystem_c.dylib❯
❲ 3❳ __assert_rtn ❮libsystem_c.dylib❯
❲ 4❳ void clang::CodeGen::CodeGenFunction::EmitCallArgs<clang::FunctionProtoType>(this=0x00007fff5fbf6738, Args=0x00007fff5fbf5588, CallArgTypeInfo=0x000000010d04dc10, ArgRange=iterator_range<clang::Stmt::ConstExprIterator> @ 0x00007fff5fbf4dd0, AC=AbstractCallee @ 0x00007fff5fbf4dc8, ParamsToSkip=0, Order=Default) at CodeGenFunction.h:3770 ❮clang-5.0❯
❲ 5❳ clang::CodeGen::CodeGenFunction::EmitCall(this=0x00007fff5fbf6738, CalleeType=QualType @ 0x00007fff5fbf5490, OrigCallee=0x00007fff5fbf5950, E=0x000000010d04df90, ReturnValue=ReturnValueSlot @ 0x00007fff5fbf5480, Chain=0x0000000000000000) at CGExpr.cpp:4468 ❮clang-5.0❯
* ❲ 6❳ clang::CodeGen::CodeGenFunction::EmitCallExpr(this=0x00007fff5fbf6738, E=0x000000010d04df90, ReturnValue=ReturnValueSlot @ 0x00007fff5fbf59e0) at CGExpr.cpp:4089 ❮clang-5.0❯
❲ 7❳ (anonymous namespace)::AggExprEmitter::VisitCallExpr(this=0x00007fff5fbf5ba8, E=0x000000010d04df90) at CGExprAgg.cpp:782 ❮clang-5.0❯
❲ 8❳ clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::AggExprEmitter, void>::Visit(this=0x00007fff5fbf5ba8, S=0x000000010d04df90) at StmtNodes.inc:329 ❮clang-5.0❯
❲ 9❳ (anonymous namespace)::AggExprEmitter::Visit(this=0x00007fff5fbf5ba8, E=0x000000010d04df90) at CGExprAgg.cpp:104 ❮clang-5.0❯
❲10❳ clang::CodeGen::CodeGenFunction::EmitAggExpr(this=0x00007fff5fbf6738, E=0x000000010d04df90, Slot=AggValueSlot @ 0x00007fff5fbf5c10) at CGExprAgg.cpp:1548 ❮clang-5.0❯
❲11❳ clang::CodeGen::CodeGenFunction::EmitAnyExpr(this=0x00007fff5fbf6738, E=0x000000010d04df90, aggSlot=AggValueSlot @ 0x00007fff5fbf5cf0, ignoreResult=true) at CGExpr.cpp:180 ❮clang-5.0❯
❲12❳ clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(this=0x00007fff5fbf6738, E=0x000000010d04df90) at CGExpr.cpp:159 ❮clang-5.0❯
❲13❳ clang::CodeGen::CodeGenFunction::EmitStmt(this=0x00007fff5fbf6738, S=0x000000010d04df90) at CGStmt.cpp:107 ❮clang-5.0❯
❲14❳ clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(this=0x00007fff5fbf6738, S=0x000000010d0512d8, GetLast=false, AggSlot=AggValueSlot @ 0x00007fff5fbf5fa0) at CGStmt.cpp:381 ❮clang-5.0❯
❲15❳ clang::CodeGen::CodeGenFunction::EmitCompoundStmt(this=0x00007fff5fbf6738, S=0x000000010d0512d8, GetLast=false, AggSlot=AggValueSlot @ 0x00007fff5fbf60f0) at CGStmt.cpp:371 ❮clang-5.0❯
❲16❳ clang::CodeGen::CodeGenFunction::EmitSimpleStmt(this=0x00007fff5fbf6738, S=0x000000010d0512d8) at CGStmt.cpp:344 ❮clang-5.0❯
❲17❳ clang::CodeGen::CodeGenFunction::EmitStmt(this=0x00007fff5fbf6738, S=0x000000010d0512d8) at CGStmt.cpp:53 ❮clang-5.0❯
❲18❳ clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(this=0x00007fff5fbf6738, S=0x000000010d05eb78, GetLast=false, AggSlot=AggValueSlot @ 0x00007fff5fbf6370) at CGStmt.cpp:381 ❮clang-5.0❯
❲19❳ clang::CodeGen::CodeGenFunction::EmitFunctionBody(this=0x00007fff5fbf6738, Args=0x00007fff5fbf6600, Body=0x000000010d05eb78) at CodeGenFunction.cpp:1035 ❮clang-5.0❯
❲20❳ clang::CodeGen::CodeGenFunction::GenerateCode(this=0x00007fff5fbf6738, GD=GlobalDecl @ 0x00007fff5fbf6588, Fn=0x000000010c81c718, FnInfo=0x000000010c81d5e0) at CodeGenFunction.cpp:1205 ❮clang-5.0❯
❲21❳ clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(this=0x000000010d819c00, GD=GlobalDecl @ 0x00007fff5fbf6730, GV=0x000000010c81c718) at CodeGenModule.cpp:3207 ❮clang-5.0❯
❲22❳ clang::CodeGen::CodeGenModule::EmitGlobalDefinition(this=0x000000010d819c00, GD=GlobalDecl @ 0x00007fff5fbf7b88, GV=0x0000000000000000) at CodeGenModule.cpp:2037 ❮clang-5.0❯
❲23❳ clang::CodeGen::CodeGenModule::EmitGlobal(this=0x000000010d819c00, GD=GlobalDecl @ 0x00007fff5fbf7d70) at CodeGenModule.cpp:1812 ❮clang-5.0❯
❲24❳ clang::CodeGen::CodeGenModule::EmitTopLevelDecl(this=0x000000010d819c00, D=0x000000010d04cc50) at CodeGenModule.cpp:3937 ❮clang-5.0❯
❲25❳ clang::CodeGeneratorImpl::HandleTopLevelDecl(this=0x000000010ce095b0, DG=DeclGroupRef @ 0x00007fff5fbf97d8) at ModuleBuilder.cpp:322 ❮clang-5.0❯
❲26❳ clang::BackendConsumer::HandleTopLevelDecl(this=0x000000010ce093d0, D=DeclGroupRef @ 0x00007fff5fbf9870) at CodeGenAction.cpp:136 ❮clang-5.0❯
(lldb) f 4
❲ 4❳ void clang::CodeGen::CodeGenFunction::EmitCallArgs<clang::FunctionProtoType>(this=0x00007fff5fbf6738, Args=0x00007fff5fbf5588, CallArgTypeInfo=0x000000010d04dc10, ArgRange=iterator_range<clang::Stmt::ConstExprIterator> @ 0x00007fff5fbf4dd0, AC=AbstractCallee @ 0x00007fff5fbf4dc8, ParamsToSkip=0, Order=Default) at CodeGenFunction.h:3770 ❮clang-5.0❯
3767 E = CallArgTypeInfo->param_type_end();
3768 I != E; ++I, ++Arg) {
3769 assert(Arg != ArgRange.end() && "Running over edge of argument list!");
-> 3770 assert((isGenericMethod ||
3771 ((*I)->isVariablyModifiedType() ||
3772 (*I).getNonReferenceType()->isObjCRetainableType() ||
3773 getContext()
(lldb) p isGenericMethod
(bool) $1 = false
(lldb) up
❲ 5❳ clang::CodeGen::CodeGenFunction::EmitCall(this=0x00007fff5fbf6738, CalleeType=QualType @ 0x00007fff5fbf5490, OrigCallee=0x00007fff5fbf5950, E=0x000000010d04df90, ReturnValue=ReturnValueSlot @ 0x00007fff5fbf5480, Chain=0x0000000000000000) at CGExpr.cpp:4468 ❮clang-5.0❯
4465 }
4466 }
4467
-> 4468 EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), E->arguments(),
4469 E->getDirectCallee(), /*ParamsToSkip*/ 0, Order);
4470
4471 const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(
(lldb) p E->dump()
CallExpr 0x10d04df90 'CladFunction<false, void, double, double, double *>':'class clad::CladFunction<false, void, double, double, double *>'
|-ImplicitCastExpr 0x10d04df78 'CladFunction<false, void, double, double, double *> (*)(double (*)(double, double), const char *)' <FunctionToPointerDecay>
| `-DeclRefExpr 0x10d04dee0 'CladFunction<false, void, double, double, double *> (double (*)(double, double), const char *)' lvalue Function 0x10d04dd40 'gradient' 'CladFunction<false, void, double, double, double *> (double (*)(double, double), const char *)' (FunctionTemplate 0x10d03cf80 'gradient')
|-ImplicitCastExpr 0x10d066070 'void (*)(double, double, double *)' <FunctionToPointerDecay>
| `-DeclRefExpr 0x10d066048 'void (double, double, double *)' lvalue Function 0x10d065cc0 'f_add1_grad' 'void (double, double, double *)'
`-ImplicitCastExpr 0x10d0661a0 'const char *' <ArrayToPointerDecay>
`-StringLiteral 0x10d066108 'const char [107]' lvalue "void f_add1_grad(double x, double y, double *_result) {\n _result[0UL] += 1.;\n _result[1UL] += 1.;\n}\n"
It looks like some of our newly generated expressions do not set some relevant properties.
@efremale, could you take a look?
For example, consider the function
double f(double x) {
auto t = x * x;
return t;
}
Currently, clad considers all intermediate variables as constants,
so dt/dx = 0, and f_darg0 will allways return 0.
Here is a reproducer:
double myFunc(double x) {
return 3.14 * x * x;
}
Currently, if differentiation process meets a function which has no defined derivative in custom_derivatives
namespace, its derivative is set to be 0
.
Example:
double f(double x) {
printf("%d", x);
return x;
}
->
double f_darg0(double x) {
0;
printf("%d", x);
return 1;
}
Since there exist no custom_derivatives::printf_darg0
, we set the derivative of printf
to be zero.
In principle, we could detect it and return null instead, but this would break cases when printf
is used in expressions, e.g. int i = x + printf(...);
-> int _d_i = _d_x + 0;
. This is an obscure case, but it makes sense to use 0 in such expressions (say, if it is not printf, but some non-differentiable math function, we cannot determine that).
Should we indicate more clearly where does this 0 come from? E.g.
double f_darg0(double x) {
int printf_darg0_non_differentiable = 0;
printf_darg0_non_differentiable;
printf("%d", x);
return 1;
}
f(x,y)=x_x + x_y + y*y
df/dx=2_x + y
df/dy=x + 2_y
d2f/dxdy = 1
For example
int i = 0;
clad::differentiate(f, i);
will result in
error: Must be an integral value,
whereas
clad::differentiate(f, 0);
will work.
This is not necessarily a problem but it is somewhat misleading.
struct Vec {
float x, y, z;
}
float sphere_implicit_func(float x, float y, float z, Vec &p, float r) {
return (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y) + (z-p.z)*(z-p.z) - r*r;
}
Fires "Assertion failed: (lhs_derived->getType() == rhs_derived->getType() && "Must be the same types."), function VisitBinaryOperator" during compilation,
but
float sphere_implicit_func(float x, float y, float z, float px, float py, float pz, float r) {
return (x-px)*(x-px) + (y-py)*(y-py) + (z-pz)*(z-pz) - r*r;
}
is OK.
For example, for a struct:
struct S {
double c;
double f(double x) { return c * x; }
};
Calling something like
clad::differentiate(&S::x, &S::c)
would produce
double f_darg_c(double x) { return x; }
Now we can only differentiate methods w.r.t. their arguments.
We should be able to assert whether clad is attached to an expected clang version. See http://clang.llvm.org/doxygen/Version_8cpp_source.html#l00074
Assertion failed: (lhs_derived->getType() == rhs_derived->getType() && "Must be the same types."), function VisitBinaryOperator, file /Users/alexanderpenev/clad/src/tools/clad/lib/Differentiator/DerivativeBuilder.cpp, line 453.
This message does not help the user. Better text should contains information on function, which can not differentiate, if possible row and column of the user program. Best messages or warnings in style clang.
Example:
double f(double x, double y) {
double t = (x - y) * (x - y);
return t;
}
->
double f_darg0(double x, double y) {
double _t0 = (x - y);
double _t1 = (x - y);
double _d_t = (1. - 0.) * _t1 + _t0 * (1. - 0.);
double t = _t0 * _t1;
return _d_t;
}
Variables _t0
and _t1
are redundant. Since the original function uses (x - y) on several places, we get several temporaries for it.
We do not check the original function for repeated expressions, it would add quite a huge computational overhead. Moreover, since it was acceptable for the original function to use the same expression repeatedly, it is presumably acceptable to do so in the derivative.
clad/lib/Differentiator/ConstantFolder.h
Line 28 in 11777b8
m_Enable is set to false, so folding has no effect.
Why?
The chained rule of differentiation produces a lot of trivial constants to fold. For example:
return 1 + (0) + (1) + (0) + (1).
Extends the work done in #47
We don't get the information about the order of the derivative from clad::differentiate(...);
double hyperbolic_octahedron_func(double x, double y, double z, const Vec &p, double r) {
x/=r; y/=r; z/=r;
return pow(x, 2/3) + pow(y, 2/3) + pow(z, 2/3) - 1;
}
generate:
double hyperbolic_octahedron_func_dx(double x, double y, double z, const Vec &p, double r) {
1. /= 0.;
0. /= 0.;
0. /= 0.;
return pow_dx(x, 2 / 3);
}
but
double hyperbolic_octahedron_func(double x, double y, double z, const Vec &p, double r) {
x=x/r; y=y/r; z=z/r;
return pow(x, 2/3) + pow(y, 2/3) + pow(z, 2/3) - 1;
}
is OK, generating:
double hyperbolic_octahedron_func_dx(double x, double y, double z, const Vec &p, double r) {
x = r / (r * r);
y = 0.;
z = 0.;
return pow_dx(x, 2 / 3);
}
Such mechanism would help clients to selectively enable the derivative computation. Eg:
#pragma clad on
// synthesized code which we know will have a call to clad::*
#pragma clad off
There are problem with internal function like sqrt. For example
float func(float x, float y) {
return sqrt(x * x + y * y) - y;
}
after clad::differentiate(func, 1) is
float func_derived_x(float x, float y) {
return sqrt(x * x + y * y) - (0.F);
}
but it must something like that:
float func_derived_x(float x, float y) {
return ((1.F * x + x * 1.F) + ((0.F * y + y * 0.F))) * (1.F / (2.F * sqrt(x * x + y * y)) - (0.F));
}
Travis is a continuous integration tool integrated well with github. We need to have CI builds.
https://travis-ci.org
This function is differentiate without problems:
float sphere_implicit_func(float x, float y, float z, float px, float py, float pz, float r) {
return (x-px)*(x-px) + (y-py)*(y-py) + (z-pz)*(z-pz) - r*r;
}
but this
float sphere_distance_func(float x, float y, float z, float px, float py, float pz, float r) {
return (x-px)*(x-px) + (y-py)*(y-py) + (z-pz)*(z-pz) - r;
}
generate compile time assertion:
Assertion failed: (lhs_derived->getType() == rhs_derived->getType() && "Must be the same types."), function VisitBinaryOperator, file /Users/alexanderpenev/clad/src/tools/clad/lib/Differentiator/DerivativeBuilder.cpp, line 453.
This workaround
float sphere_distance_func(float x, float y, float z, float px, float py, float pz, float r) {
return (x-px)*(x-px) + (y-py)*(y-py) + (z-pz)*(z-pz) - r*1.0f;
}
also is OK.
The idea is to replace each type RealT
with the type dual<RealT, RealT>
, where dual
has overloaded operators such that the first element is the same as the original value and the second element is the value of its derivative. This is easy to achieve by employing basic differentiation rules for operators.
On the first sight, it appears to be a much easier way of supporting more general C++ constructs as they need not be treated separately anymore.
Similar idea is in "Automatic Differentiation in 10 minutes with Julia": https://www.youtube.com/watch?v=vAp6nUMrKYg&t=683s
float f(float x) { return x + 25.f; }
For example:
template<typename T> T F(T x) { return std::sin<T>(x); }
Differentiate
struct Vec { float x,y,z; };
float f_const_args_func_4(float x, float y, const Vec v) {
return x * x + y * y - v.x;
}
return
float f_const_args_func_4_dx(const float x, const float y, const Vec v) {
return (1.F * x + x * 1.F) + ((0.F * y + y * 0.F)) - (v.x);
}
but we expect
float f_const_args_func_4_dx(const float x, const float y, const Vec v) {
return (1.F * x + x * 1.F) + ((0.F * y + y * 0.F)) - (0.F);
}
clad/lib/Differentiator/DerivativeBuilder.cpp
Line 487 in 953fe26
This is inefficient if no derivative for the callee exist. It can potentially lead to errors since it is likely that nondifferentiable function call has nondifferentiable arguments as well.
Each call to Clone() has complexity of O(n), where n is the size of the Stmt's subtree, since it recursively calls Clone() on every substatement until leaves are reached.
When differentiating a function via Forward/ReverseModeVisitor, we potentially call Clone() on every node of the AST tree (which recursively clones all subnodes, we are cloning same nodes multiple times) and have the total complexity of O(n^2).
Wouldn't it be more efficient to Clone() the whole tree just once before calling Visit() on it? The complexity should be just 2xO(n).
For example:
double foo(double);
clad::differentiate(foo,0);
We should probably have a similar to this check earlier (on a DiffPlanner level).
Currently we just crash ;)
Now we pass the output _result
array to gradient functions as a last parameter.
This causes some problems, e.g.,
default parameter values cannot be used as the _result
parameter is last and has no default value.
This leads to generation of functions like
void f_grad(double x, double y = default_y, double* _result);
where there is no way to actually call it with default_y
value.
Some problems may also arise when f
or f_grad
is declared as variadic template function.
Are there better solutions?
Does it make sense to pass _result
as a first parameter?
A call to itself inside a function body is not treated correctly.
For example, if we differentiate
double r(double x) {
if (x > 0)
return r(x-1);
else
return x;
the call r(x-1) is treated as a call to some other function and we get the warning: function 'r' was not differentiated because it is not declared in namespace 'custom_derivatives' attempted differention of function 'r', which does not have a definition.
The following derivative is generated:
double r_darg0(double x) {
if (x > 0)
return r(x-1);
else
return 1.0;
but the correct derivative would be
double r_darg0(double x) {
if (x > 0)
return r_darg0(x-1) * 1.0;
else
return 1.0;
Currently, if we Visit unsupported statement (e.g. try-catch, range for loop), it is simply cloned without changes and a warning is emitted.
Should we instead emit a hard error and not produce the derivative?
This is somewhat harder to achieve now.
How should the error be promoted in the visitor?
If we return null StmtDiff whenever we meet an unsupported statement, we would have to add a lot of checks for null.
We cannot throw an exception sice clang disables them.
We can set some bool flag and keep visiting function and check for the error flag in the end, but it is inefficient and error-prone.
class A {
public:
virtual float vm(float x, float y) {
return x + y;
}
};
class B : public A {
public:
float vm(float x, float y) override {
return x*x + y*y;
}
};
int main() {
auto vm_darg0_A = clad::differentiate(&A::vm, 0);
printf("Result is = %f\n", vm_darg0_A.execute(a, 2, 3)); // CHECK-EXEC: Result is = 1.0000
auto vm_darg0_B = clad::differentiate(&B::vm, 0);
printf("Result is = %f\n", vm_darg0_B.execute(b, 2, 3)); // CHECK-EXEC: Result is = 4.0000
}
For some reason vm_darg0_A.execute(a, 2, 3) calls the B::vm. If the execute()-s get swapped it works as expected.
When embedded in ROOT we want to build clad with external LLVM but internal clang. Currently there is not way of detecting this and we pick up the wrong header files which manifest into a very hard-to-find bug.
Even if -DCLAD_PATH_TO_LLVM_BUILD
is passed, the system llvm is discovered first.
/cvmfs/sft.cern.ch/lcg/releases/CMake/3.11.1-773ff/x86_64-centos7-gcc62-opt/bin/cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/cvmfs/projects.cern.ch/intelsw/psxe/linux/x86_64/2018/compilers_and_libraries_2018.2.199/linux/bin/intel64/icc -DCMAKE_C_FLAGS= -restrict -wd1572 -m64 -wd279 -wd873 -wd2536 -wd597 -wd1098 -wd1292 -wd1478 -wd3373 -pthread -fPIC -Werror=date-time -w -ffunction-sections -fdata-sections -DCMAKE_CXX_COMPILER=/cvmfs/projects.cern.ch/intelsw/psxe/linux/x86_64/2018/compilers_and_libraries_2018.2.199/linux/bin/intel64/icc -DCMAKE_CXX_FLAGS= -wd1476 -wd1572 -m64 -wd279 -wd873 -wd2536 -wd597 -wd1098 -wd1292 -wd1478 -wd3373 -pthread -std=c++11 -fPIC -fvisibility-inlines-hidden -Werror=date-time -std=c++11 -w -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -fno-strict-aliasing -Wno-nested-anon-types -Wno-covered-switch-default -Wno-unused-local-typedef -fno-rtti -DCMAKE_INSTALL_PREFIX=/data/sftnight/workspace/root-benchmark/BUILDTYPE/Release/COMPILER/icc18/LABEL/performance-sandy-cc7/build/etc/cling/plugins/ -DCLAD_PATH_TO_LLVM_BUILD=/data/sftnight/workspace/root-benchmark/BUILDTYPE/Release/COMPILER/icc18/LABEL/performance-sandy-cc7/build/interpreter/llvm/src -G"Unix Makefiles" /data/sftnight/workspace/root-benchmark/BUILDTYPE/Release/COMPILER/icc18/LABEL/performance-sandy-cc7/build/interpreter/llvm/src/tools/cling/tools/plugins/clad/clad-prefix/src/clad
-- Could NOT find Subversion (missing: Subversion_SVN_EXECUTABLE)
CMake Error at /opt/llvm-5.0.1/lib64/cmake/llvm/LLVMExports.cmake:960 (message):
The imported target "LLVMDemangle" references the file
"/opt/llvm-5.0.1/lib64/libLLVMDemangle.a"
but this file does not exist. Possible reasons include:
* The file was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and contained
"/opt/llvm-5.0.1/lib64/cmake/llvm/LLVMExports.cmake"
but not all the files it references.
Call Stack (most recent call first):
/opt/llvm-5.0.1/lib64/cmake/llvm/LLVMConfig.cmake:188 (include)
CMakeLists.txt:8 (find_package)
-- Configuring incomplete, errors occurred!
Now we can only compute gradients w.r.t. to every argument of a function.
For efficiency reasons, it seems to be a good idea to be able to specify indices required of independent variables, e.g.:
clad::gradient(f, 0, 2, 4)
or
clad::gradient(f, {0, 2, 4})
or even
clad::gradient(f, std::index_sequence<0, 2, 4>{})
Hi,
The suffix of the derivatives should be darg0, darg1, ... dargN, because we can have scenarios where the users rely on using builtin derivatives. For example:
Builtins.h
float builtin_f(float x, double y); // in builtin derivatives becomes
float builtin_fdx(float x, double y) {}
And the user file:
float builtin_f(float a, double b);
float f(float t, float u) {
// Here clad won't be able to find builtin_fdx, because there is not enough info in the call
return t * u * builtin_f(t, u);
}
Vassil
double pow(double x);
then pow_dx(4.2); does not work. execute and funtionpointer usage work.
double myFunc(double x) -> double d_myFunc_dx(double x). The second derivative: double d2_myFunc_dx2(double x);
Support double f(double*, unsigned numElements); The user should be able to specify the independent variable from a given array of variables.
For example:
double sphere_implicit_func(double x, double y, double z, const Vec &p, double r) {
return (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y) + (z-p.z)*(z-p.z) - r*r;
}
generate:
double sphere_implicit_func_dx(double x, double y, double z, const Vec &p, double r) {
return ((x - p.x) + (x - p.x));
}
double sphere_implicit_func_dy(double x, double y, double z, const Vec &p, double r) {
return 0. + ((y - p.y) + (y - p.y));
}
double sphere_implicit_func_dz(double x, double y, double z, const Vec &p, double r) {
return 0. + ((z - p.z) + (z - p.z));
}
If we have
class A {
public:
int f(int x) {
return x;
}
virtual float vm(float x, float y) {
return x + y;
}
}
class B : public A {
public:
float vm(float x, float y) override {
return x*x + y*y;
}
}
int main() {
A a;
B b;
clad::differentiate(&A::f, 0);
clad::differentiate(&A::vm, 0);
printf("Result is = %f\n", a.vm_dx(2,3)); // Result is = 2.F
clad::differentiate(&B::vm, 0);
printf("Result is = %f\n", a.vm_dx(2,3)); // Result is = 4.F
return 0;
}
clad throw error and assert message
error: no member named 'vm_dx' in 'A'
printf("Result is = %f\n", a.vm_dx(2,3));
~ ^
...
Assertion failed: (Access != AS_none && "Access specifier is AS_none inside a record decl"), function AccessDeclContextSanity, file /Users/alexanderpenev/clad/src/tools/clang/lib/AST/DeclBase.cpp, line 701.
Example:
double f(double x) {
double t = 2 * (-x);
return t;
}
->
double f_darg0(double x) {
double _t0 = -x;
double _d_t = 0 * _t0 + 2 * -1.;
double t = 2 * _t0;
return _d_t;
}
In this case, double _t0 = -x
seems useless so it makes sense to add such simple unary operators to a list of cases for which temporaries are not generated (now it is literals and references). On the other hand, results of unary operators like ++x
must be stored to avoid repeated increment.
Can be reproduced by
struct S{
int f0() { return 0; }
int f1(int x) { return f0() + x; }
};
...
clad::differentiate(&S::f1, 0);
This work:
// Necessary for clad to work include
#include "clad/Differentiator/Differentiator.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
This generate compile time assert ("Cannot find builtin derivatives!"):
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
// Necessary for clad to work include
#include "clad/Differentiator/Differentiator.h"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.