Missing derivative description for `fabs`
Closed this issue · 2 comments
I had finally time to continue using clad. I get now an error for fabs
.
When compiling:
#include "clad/Differentiator/Differentiator.h"
#include <iostream>
#include <cmath>
void f(double* x, double* y, int size) {
y[0] = std::fabs(x[0]);
}
namespace custom_derivatives {
namespace std {
void fabs_grad(double x, clad::array_ref<double> _d_x) { *_d_x = x == 0.0 ? 0.0 : x < 0.0 ? -1.0 : 1.0; }
}
}
int main() {
auto f_dx = clad::gradient(f);
f_dx.dump();
}
I get the output:
fabs_error.cpp:7:10: warning: function 'fabs' was not differentiated because clad failed to differentiate it and no suitable overload was found in namespace 'custom_derivatives'
7 | y[0] = std::fabs(x[0]);
| ^
fabs_error.cpp:7:10: note: falling back to numerical differentiation for 'fabs' since no suitable overload was found and clad could not derive it; to disable this feature, compile your programs with -DCLAD_NO_NUM_DIFF
1 warning generated.
I tried to define a custom derivative function after https://github.com/vgvassilev/clad?tab=readme-ov-file#specifying-custom-derivatives but this did not work:
namespace custom_derivatives {
namespace std {
void fabs_grad(double x, clad::array_ref<double> _d_x) { *_d_x = x == 0.0 ? 0.0 : x < 0.0 ? -1.0 : 1.0; }
}
}
The documentation for custom derivatives seems incomplete: https://clad.readthedocs.io/en/latest/user/CoreConcepts.html#custom-derivatives
In my real world usecase I get an exception afterwards:
/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/cmath:239:12: warning: function '__builtin_fabsf' was not differentiated because clad failed to differentiate it and no suitable overload was found in namespace 'custom_derivatives'
239 | { return __builtin_fabsf(__x); }
| ^
/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/cmath:239:12: note: falling back to numerical differentiation for '__builtin_fabsf' since no suitable overload was found and clad could not derive it; to disable this feature, compile your programs with -DCLAD_NO_NUM_DIFF
/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/cmath:239:12: error: internal error: could not emit constant value "abstractly"
239 | { return __builtin_fabsf(__x); }
| ^
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0. Program arguments: clang++ -fplugin=/home/msagebaum/Applications/clad/inst/lib/clad.so -I/home/msagebaum/Applications/clad/inst/include -Xclang -plugin-arg-clad -Xclang -fgenerate-source-file -I/usr/include/openmpi-x86_64 -I../trace/INCLUDE -I../build_normal_opt/trace visc.c -c -o visc.o
1. <eof> parser at end of file
2. Per-file LLVM IR generation
3. Generating code for declaration 'std::fabs_pullback'
4. visc.c:1:1: LLVM IR generation of compound statement ('{}')
#0 0x00000000032807cb llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x32807cb)
#1 0x000000000327e5e4 llvm::sys::CleanupOnSignal(unsigned long) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x327e5e4)
#2 0x00000000031c75e8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#3 0x00007fc1a304fd00 __restore_rt (/lib64/libc.so.6+0x40d00)
#4 0x0000000002c84ae2 llvm::Type::isIntegerTy(unsigned int) const (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x2c84ae2)
#5 0x0000000003633b2d clang::CodeGen::CodeGenTypes::ConvertTypeForMem(clang::QualType, bool) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3633b2d)
#6 0x0000000003525885 clang::CodeGen::CodeGenModule::EmitNullConstant(clang::QualType) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3525885)
#7 0x0000000003601437 clang::CodeGen::CodeGenModule::createOpenCLIntToSamplerConversion(clang::Expr const*, clang::CodeGen::CodeGenFunction&) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3601437)
#8 0x000000000393b202 (anonymous namespace)::ScalarExprEmitter::VisitCastExpr(clang::CastExpr*) CGExprScalar.cpp:0:0
#9 0x000000000393bebf clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x393bebf)
#10 0x00000000038df5af clang::CodeGen::CodeGenFunction::EmitAnyExpr(clang::Expr const*, clang::CodeGen::AggValueSlot, bool) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x38df5af)
#11 0x00000000038df929 clang::CodeGen::CodeGenFunction::EmitAnyExprToTemp(clang::Expr const*) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x38df929)
#12 0x0000000003879da8 clang::CodeGen::CodeGenFunction::EmitCallArg(clang::CodeGen::CallArgList&, clang::Expr const*, clang::QualType) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3879da8)
#13 0x000000000387b454 clang::CodeGen::CodeGenFunction::EmitCallArgs(clang::CodeGen::CallArgList&, clang::CodeGen::CodeGenFunction::PrototypeWrapper, llvm::iterator_range<clang::Stmt::CastIterator<clang::Expr, clang::Expr const* const, clang::Stmt const* const>>, clang::CodeGen::CodeGenFunction::AbstractCallee, unsigned int, clang::CodeGen::CodeGenFunction::EvaluationOrder) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x387b454)
#14 0x00000000038e5681 clang::CodeGen::CodeGenFunction::EmitCall(clang::QualType, clang::CodeGen::CGCallee const&, clang::CallExpr const*, clang::CodeGen::ReturnValueSlot, llvm::Value*) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x38e5681)
#15 0x00000000038ed2bc clang::CodeGen::CodeGenFunction::EmitCallExpr(clang::CallExpr const*, clang::CodeGen::ReturnValueSlot) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x38ed2bc)
#16 0x000000000393d17b (anonymous namespace)::ScalarExprEmitter::VisitCallExpr(clang::CallExpr const*) CGExprScalar.cpp:0:0
#17 0x0000000003940ae9 clang::CodeGen::CodeGenFunction::EmitPromotedScalarExpr(clang::Expr const*, clang::QualType) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3940ae9)
#18 0x00000000039413f4 (anonymous namespace)::ScalarExprEmitter::EmitBinOps(clang::BinaryOperator const*, clang::QualType) CGExprScalar.cpp:0:0
#19 0x00000000039373ae clang::StmtVisitorBase<std::add_pointer, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit(clang::Stmt*) CGExprScalar.cpp:0:0
#20 0x000000000393872a (anonymous namespace)::ScalarExprEmitter::Visit(clang::Expr*) CGExprScalar.cpp:0:0
#21 0x000000000394204d (anonymous namespace)::ScalarExprEmitter::EmitCompoundAssignLValue(clang::CompoundAssignOperator const*, llvm::Value* ((anonymous namespace)::ScalarExprEmitter::*)((anonymous namespace)::BinOpInfo const&), llvm::Value*&) (.constprop.0) CGExprScalar.cpp:0:0
#22 0x00000000039433cf clang::CodeGen::CodeGenFunction::EmitCompoundAssignmentLValue(clang::CompoundAssignOperator const*) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x39433cf)
#23 0x00000000038ed9da clang::CodeGen::CodeGenFunction::EmitLValueHelper(clang::Expr const*, clang::CodeGen::KnownNonNull_t) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x38ed9da)
#24 0x00000000038eccb9 clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(clang::Expr const*) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x38eccb9)
#25 0x000000000354b042 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x354b042)
#26 0x0000000003550c09 clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3550c09)
#27 0x0000000003550f2c clang::CodeGen::CodeGenFunction::EmitCompoundStmt(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3550f2c)
#28 0x00000000035512e1 clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x35512e1)
#29 0x000000000354af82 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x354af82)
#30 0x0000000003550c09 clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3550c09)
#31 0x00000000035a79e9 clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::Stmt const*) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x35a79e9)
#32 0x00000000035b9e13 clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x35b9e13)
#33 0x00000000036018c1 clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x36018c1)
#34 0x00000000035fd8ec clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x35fd8ec)
#35 0x0000000003605bcf clang::CodeGen::CodeGenModule::EmitDeferred() (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3605bcf)
#36 0x0000000003605beb clang::CodeGen::CodeGenModule::EmitDeferred() (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3605beb)
#37 0x0000000003606db0 clang::CodeGen::CodeGenModule::Release() (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3606db0)
#38 0x00000000043c34aa (anonymous namespace)::CodeGeneratorImpl::HandleTranslationUnit(clang::ASTContext&) ModuleBuilder.cpp:0:0
#39 0x00000000043c1385 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x43c1385)
#40 0x0000000003cfb308 clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3cfb308)
#41 0x00007fc1a2714bc6 clad::plugin::CladPlugin::HandleTranslationUnit(clang::ASTContext&) /home/msagebaum/Applications/clad/tools/ClangPlugin.cpp:468:5
#42 0x0000000003cfb308 clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3cfb308)
#43 0x0000000005163489 clang::ParseAST(clang::Sema&, bool, bool) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x5163489)
#44 0x0000000003cbeb81 clang::FrontendAction::Execute() (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3cbeb81)
#45 0x0000000003c4a15b clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3c4a15b)
#46 0x0000000003d7dbeb clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3d7dbeb)
#47 0x0000000000b0139d cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0xb0139d)
#48 0x0000000000af9f47 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#49 0x0000000003a88ca9 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#50 0x00000000031c79b3 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x31c79b3)
#51 0x0000000003a8906e clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#52 0x0000000003a52de5 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3a52de5)
#53 0x0000000003a5386d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3a5386d)
#54 0x0000000003a6461c clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x3a6461c)
#55 0x0000000000afef9d clang_main(int, char**, llvm::ToolContext const&) (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0xafef9d)
#56 0x00000000009ed831 main (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0x9ed831)
#57 0x00007fc1a3039088 __libc_start_call_main (/lib64/libc.so.6+0x2a088)
#58 0x00007fc1a303914b __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x2a14b)
#59 0x0000000000af93a5 _start (/home/msagebaum/Applications/llvm-project-llvmorg-17.0.6/install/bin/clang-17+0xaf93a5)
clang++: error: clang frontend command failed with exit code 139 (use -v to see invocation)
hi Max!
first of all, in here, where you specify the custom derivative, you're missing the wrapping clad
namespace:
// your code:
namespace custom_derivatives {
namespace std {
void fabs_grad(double x, clad::array_ref<double> _d_x) { *_d_x = x == 0.0 ? 0.0 : x < 0.0 ? -1.0 : 1.0; }
}
}
// should be smth equivalent to:
namespace clad::custom_derivatives::std {
...
}
so I assume the compiler can't find this specification.
now, second of all, there's a tricky thing about Clad. in the reverse mode, when the function called is a simple pure function with 1 argument and 1 output value Clad actually doesn't use a pullback to compute the derivative/adjoint of its value. instead, it simplifies the computations and uses the pushforward.
so here's a working example solving your issue:
#include "clad/Differentiator/Differentiator.h"
#include <iostream>
#include <cmath>
void f(double* x, double* y, int size) {
y[0] = std::fabs(x[0]);
}
namespace clad {
namespace custom_derivatives {
namespace std {
ValueAndPushforward<double, double> fabs_pushforward(double x, double d_x) {
if (x >= 0)
return {x, d_x};
return {-x, -d_x};
}
}
using std::fabs_pushforward; // (* -- this line is explained below)
}
}
int main() {
auto f_dx = clad::gradient(f);
f_dx.dump();
}
- -- the starred line is another tricky thing about specifying custom derivatives for
std
functions. in some implementations, these functions are defined with a certain namespace re-wrapping, so you might need this line for this code to work. this is something I learned not so long ago as well :)
hope this helps
Maybe we should open a PR to provide it as part of the stl builtins?