You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add an opt-in mechanism for non-differentiable types.
When clad has no custom derivative for a called function it synthesizes
one by cloning the function's body. For a type whose internals are not
meant to be differentiated -- a standard-library primitive, an I/O
stream -- that clone is at best wasteful and at worst ill-formed:
cloning std::string's char-pointer constructor emits a static
reverse-forward propagator that dereferences a null `this` and crashes
CodeGen.
A type is now non-differentiable when it carries the `non_differentiable`
annotation -- on the type itself for code the user owns
(CLAD_NONDIFFERENTIABLE), or on a clad::Tag<T> specialization for a
foreign type the user cannot annotate at its declaration
(CLAD_NONDIFFERENTIABLE_TYPE). utils::isNonDifferentiableType detects it,
so clad never clones such a type's constructor or member bodies, and
callOperatesOnNonDifferentiableType extends the treatment to a call whose
object is opaque (e.g. a std::ostream operation). Seed std::string,
std::allocator and the stream family in STLBuiltins.h.
-fclad-porting-hints prints the paste-able CLAD_NONDIFFERENTIABLE_TYPE
spelling and, for a reverse-forward pass, the elidable_reverse_forw
route with its signature -- pointing at existing mechanisms rather than
inventing new ones. isElidableConstructor is renamed to
constructorReverseForwIsElidable and documented so its "a trivial copy is
a shallow share" coverage is discoverable; that made a separate
data-less-copy heuristic unnecessary.
The user guide documents both macros; tests cover marker-based
construction opacity (StringConstructor) and a marked-type call
(NonDifferentiableMarkedType).
Copy file name to clipboardExpand all lines: docs/userDocs/source/user/UsingClad.rst
+41-12Lines changed: 41 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -598,36 +598,65 @@ The ``non_differentiable`` Attribute
598
598
599
599
Occasionally, you may want to skip differentiating a specific variable or function call. For example, some variables might be used purely for logging, as constants, or as standalone metrics. Clad provides the ``non_differentiable`` annotation attribute to safely omit generating derivatives for these components.
600
600
601
-
You can apply this attribute using Clang's annotation syntax. The most common approach is to define a macro alias:
601
+
Clad ships the ``CLAD_NONDIFFERENTIABLE`` macro (defined in
602
+
``clad/Differentiator/BuiltinDerivatives.h``, pulled in by ``Differentiator.h``)
603
+
for this; it expands to ``__attribute__((annotate("non_differentiable")))``.
If the ``non_differentiable`` attribute is applied to a variable, Clad skips generating a derivative counterpart for it:
605
+
If ``CLAD_NONDIFFERENTIABLE`` is applied to a variable, Clad skips generating a
606
+
derivative counterpart for it:
608
607
609
608
.. code-block:: c++
610
609
611
610
class PointData {
612
611
public:
613
612
double x;
614
613
double y;
615
-
non_differentiable double weight; // Clad will not compute derivatives with respect to this member
614
+
CLAD_NONDIFFERENTIABLE double weight; // not differentiated
616
615
};
617
616
618
617
If the attribute is applied to a function declaration, Clad refrains from producing any derivative expressions for that specific function. Instead, calls to the primal function are injected directly, behaving as if the result has a zero derivative:
619
618
620
619
.. code-block:: c++
621
620
622
-
non_differentiable double get_scaling_factor(double i, double j) {
623
-
return i * j;
621
+
CLAD_NONDIFFERENTIABLE double get_scaling_factor(double i, double j) {
622
+
return i * j;
624
623
}
625
624
626
-
double compute(double i, double j) {
627
-
// get_scaling_factor will skip differentiation completely.
628
-
return get_scaling_factor(i, j) + i * j;
625
+
double compute(double i, double j) {
626
+
// get_scaling_factor will skip differentiation completely.
627
+
return get_scaling_factor(i, j) + i * j;
628
+
}
629
+
630
+
Marking a type you do not own
631
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
632
+
633
+
The attribute must sit on the declaration you want to mark, so it cannot be
634
+
attached to a library type declared in a header you do not control (a stream, an
635
+
allocator, a third-party handle). For those, mark the type from the outside with
636
+
``CLAD_NONDIFFERENTIABLE_TYPE`` at global scope; Clad then treats every
0 commit comments