Skip to content

Commit 3732c3c

Browse files
authored
Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk
Start documenting autodiff activities Some initial documentation of the autodiff macros and usage examples
2 parents 714f1ce + f5892da commit 3732c3c

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

‎library/core/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ optimize_for_size = []
2323
# Make `RefCell` store additional debugging information, which is printed out when
2424
# a borrow error occurs
2525
debug_refcell = []
26+
llvm_enzyme = []
2627

2728
[lints.rust.unexpected_cfgs]
2829
level = "warn"
@@ -38,4 +39,6 @@ check-cfg = [
3839
'cfg(target_has_reliable_f16_math)',
3940
'cfg(target_has_reliable_f128)',
4041
'cfg(target_has_reliable_f128_math)',
42+
'cfg(llvm_enzyme)',
43+
4144
]

‎library/core/src/macros/mod.rs‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
14991499
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15001500
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15011501
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1502+
///
1503+
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
1504+
///
1505+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1506+
/// if we are not interested in computing the derivatives with respect to this argument.
1507+
///
1508+
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
1509+
/// indirect input arguments. It can also be used on a scalar float return value.
1510+
/// If used on a return value, the generated function will return a tuple of two float scalars.
1511+
/// If used on an input argument, a new shadow argument of the same type will be created,
1512+
/// directly following the original argument.
1513+
///
1514+
/// ### Usage examples:
1515+
///
1516+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1517+
/// #![feature(autodiff)]
1518+
/// use std::autodiff::*;
1519+
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
1520+
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
1521+
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
1522+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1523+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1524+
/// }
1525+
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
1526+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1527+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1528+
/// }
1529+
///
1530+
/// fn main() {
1531+
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
1532+
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
1533+
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
1534+
/// // When seeding both arguments at once the tangent return is the sum of both.
1535+
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
1536+
///
1537+
/// let mut out = 0.0;
1538+
/// let mut dout = 0.0;
1539+
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
1540+
/// // (out, dout) == (400.0, -400.0)
1541+
/// }
1542+
/// ```
1543+
///
1544+
/// We might want to track how one input float affects one or more output floats. In this case,
1545+
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
1546+
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
1547+
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
1548+
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
1549+
/// more efficient if we have more output floats marked as `Dual` than input floats.
1550+
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
15021551
#[unstable(feature = "autodiff", issue = "124509")]
15031552
#[allow_internal_unstable(rustc_attrs)]
15041553
#[allow_internal_unstable(core_intrinsics)]
@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
15181567
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15191568
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15201569
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1570+
///
1571+
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
1572+
///
1573+
/// `Active` can be used for float scalar values.
1574+
/// If used on an input, a new float will be appended to the return tuple of the generated
1575+
/// function. If the function returns a float scalar, `Active` can be used for the return as
1576+
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
1577+
///
1578+
/// `Duplicated` can be used on references, raw pointers, or other indirect input
1579+
/// arguments. It creates a new shadow argument of the same type, following the original argument.
1580+
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
1581+
///
1582+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1583+
/// if we are not interested in computing the derivatives with respect to this argument.
1584+
///
1585+
/// ### Usage examples:
1586+
///
1587+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1588+
/// #![feature(autodiff)]
1589+
/// use std::autodiff::*;
1590+
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
1591+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1592+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1593+
/// }
1594+
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
1595+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1596+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1597+
/// }
1598+
///
1599+
/// fn main() {
1600+
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
1601+
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
1602+
/// let mut output2 = 0.0;
1603+
/// let mut seed = 1.0;
1604+
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
1605+
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
1606+
/// }
1607+
/// ```
1608+
///
1609+
///
1610+
/// We often want to track how one or more input floats affect one output float. This output can
1611+
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
1612+
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
1613+
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
1614+
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
1615+
/// shadow of the outputs ("seed") will be reset to zero.
1616+
/// If the function has more than one output float marked as active or duplicated, users might want to
1617+
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.
1618+
/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
1619+
/// inputs.
1620+
/// Reverse mode is generally more efficient if we have more active/duplicated input than
1621+
/// output floats.
1622+
///
1623+
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
15211624
#[unstable(feature = "autodiff", issue = "124509")]
15221625
#[allow_internal_unstable(rustc_attrs)]
15231626
#[allow_internal_unstable(core_intrinsics)]

‎library/std/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
126126
# a borrow error occurs
127127
debug_refcell = ["core/debug_refcell"]
128128

129+
llvm_enzyme = ["core/llvm_enzyme"]
129130

130131
# Enable std_detect features:
131132
std_detect_file_io = ["std_detect/std_detect_file_io"]

‎library/sysroot/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
3535
std_detect_file_io = ["std/std_detect_file_io"]
3636
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
3737
windows_raw_dylib = ["std/windows_raw_dylib"]
38+
llvm_enzyme = ["std/llvm_enzyme"]

‎src/bootstrap/src/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,10 @@ impl Build {
846846
features.insert("compiler-builtins-mem");
847847
}
848848

849+
ifself.config.llvm_enzyme{
850+
features.insert("llvm_enzyme");
851+
}
852+
849853
features.into_iter().collect::<Vec<_>>().join(" ")
850854
}
851855

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk · rust-lang/rust@3732c3c · GitHub
Skip to content

Commit 3732c3c

Browse files
authored
Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk
Start documenting autodiff activities Some initial documentation of the autodiff macros and usage examples
2 parents 714f1ce + f5892da commit 3732c3c

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

‎library/core/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ optimize_for_size = []
2323
# Make `RefCell` store additional debugging information, which is printed out when
2424
# a borrow error occurs
2525
debug_refcell = []
26+
llvm_enzyme = []
2627

2728
[lints.rust.unexpected_cfgs]
2829
level = "warn"
@@ -38,4 +39,6 @@ check-cfg = [
3839
'cfg(target_has_reliable_f16_math)',
3940
'cfg(target_has_reliable_f128)',
4041
'cfg(target_has_reliable_f128_math)',
42+
'cfg(llvm_enzyme)',
43+
4144
]

‎library/core/src/macros/mod.rs‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
14991499
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15001500
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15011501
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1502+
///
1503+
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
1504+
///
1505+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1506+
/// if we are not interested in computing the derivatives with respect to this argument.
1507+
///
1508+
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
1509+
/// indirect input arguments. It can also be used on a scalar float return value.
1510+
/// If used on a return value, the generated function will return a tuple of two float scalars.
1511+
/// If used on an input argument, a new shadow argument of the same type will be created,
1512+
/// directly following the original argument.
1513+
///
1514+
/// ### Usage examples:
1515+
///
1516+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1517+
/// #![feature(autodiff)]
1518+
/// use std::autodiff::*;
1519+
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
1520+
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
1521+
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
1522+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1523+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1524+
/// }
1525+
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
1526+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1527+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1528+
/// }
1529+
///
1530+
/// fn main() {
1531+
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
1532+
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
1533+
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
1534+
/// // When seeding both arguments at once the tangent return is the sum of both.
1535+
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
1536+
///
1537+
/// let mut out = 0.0;
1538+
/// let mut dout = 0.0;
1539+
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
1540+
/// // (out, dout) == (400.0, -400.0)
1541+
/// }
1542+
/// ```
1543+
///
1544+
/// We might want to track how one input float affects one or more output floats. In this case,
1545+
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
1546+
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
1547+
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
1548+
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
1549+
/// more efficient if we have more output floats marked as `Dual` than input floats.
1550+
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
15021551
#[unstable(feature = "autodiff", issue = "124509")]
15031552
#[allow_internal_unstable(rustc_attrs)]
15041553
#[allow_internal_unstable(core_intrinsics)]
@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
15181567
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15191568
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15201569
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1570+
///
1571+
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
1572+
///
1573+
/// `Active` can be used for float scalar values.
1574+
/// If used on an input, a new float will be appended to the return tuple of the generated
1575+
/// function. If the function returns a float scalar, `Active` can be used for the return as
1576+
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
1577+
///
1578+
/// `Duplicated` can be used on references, raw pointers, or other indirect input
1579+
/// arguments. It creates a new shadow argument of the same type, following the original argument.
1580+
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
1581+
///
1582+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1583+
/// if we are not interested in computing the derivatives with respect to this argument.
1584+
///
1585+
/// ### Usage examples:
1586+
///
1587+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1588+
/// #![feature(autodiff)]
1589+
/// use std::autodiff::*;
1590+
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
1591+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1592+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1593+
/// }
1594+
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
1595+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1596+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1597+
/// }
1598+
///
1599+
/// fn main() {
1600+
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
1601+
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
1602+
/// let mut output2 = 0.0;
1603+
/// let mut seed = 1.0;
1604+
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
1605+
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
1606+
/// }
1607+
/// ```
1608+
///
1609+
///
1610+
/// We often want to track how one or more input floats affect one output float. This output can
1611+
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
1612+
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
1613+
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
1614+
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
1615+
/// shadow of the outputs ("seed") will be reset to zero.
1616+
/// If the function has more than one output float marked as active or duplicated, users might want to
1617+
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.
1618+
/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
1619+
/// inputs.
1620+
/// Reverse mode is generally more efficient if we have more active/duplicated input than
1621+
/// output floats.
1622+
///
1623+
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
15211624
#[unstable(feature = "autodiff", issue = "124509")]
15221625
#[allow_internal_unstable(rustc_attrs)]
15231626
#[allow_internal_unstable(core_intrinsics)]

‎library/std/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
126126
# a borrow error occurs
127127
debug_refcell = ["core/debug_refcell"]
128128

129+
llvm_enzyme = ["core/llvm_enzyme"]
129130

130131
# Enable std_detect features:
131132
std_detect_file_io = ["std_detect/std_detect_file_io"]

‎library/sysroot/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
3535
std_detect_file_io = ["std/std_detect_file_io"]
3636
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
3737
windows_raw_dylib = ["std/windows_raw_dylib"]
38+
llvm_enzyme = ["std/llvm_enzyme"]

‎src/bootstrap/src/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,10 @@ impl Build {
846846
features.insert("compiler-builtins-mem");
847847
}
848848

849+
ifself.config.llvm_enzyme{
850+
features.insert("llvm_enzyme");
851+
}
852+
849853
features.into_iter().collect::<Vec<_>>().join(" ")
850854
}
851855

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk · rust-lang/rust@3732c3c · GitHub
Skip to content

Commit 3732c3c

Browse files
authored
Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk
Start documenting autodiff activities Some initial documentation of the autodiff macros and usage examples
2 parents 714f1ce + f5892da commit 3732c3c

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

‎library/core/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ optimize_for_size = []
2323
# Make `RefCell` store additional debugging information, which is printed out when
2424
# a borrow error occurs
2525
debug_refcell = []
26+
llvm_enzyme = []
2627

2728
[lints.rust.unexpected_cfgs]
2829
level = "warn"
@@ -38,4 +39,6 @@ check-cfg = [
3839
'cfg(target_has_reliable_f16_math)',
3940
'cfg(target_has_reliable_f128)',
4041
'cfg(target_has_reliable_f128_math)',
42+
'cfg(llvm_enzyme)',
43+
4144
]

‎library/core/src/macros/mod.rs‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
14991499
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15001500
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15011501
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1502+
///
1503+
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
1504+
///
1505+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1506+
/// if we are not interested in computing the derivatives with respect to this argument.
1507+
///
1508+
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
1509+
/// indirect input arguments. It can also be used on a scalar float return value.
1510+
/// If used on a return value, the generated function will return a tuple of two float scalars.
1511+
/// If used on an input argument, a new shadow argument of the same type will be created,
1512+
/// directly following the original argument.
1513+
///
1514+
/// ### Usage examples:
1515+
///
1516+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1517+
/// #![feature(autodiff)]
1518+
/// use std::autodiff::*;
1519+
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
1520+
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
1521+
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
1522+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1523+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1524+
/// }
1525+
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
1526+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1527+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1528+
/// }
1529+
///
1530+
/// fn main() {
1531+
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
1532+
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
1533+
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
1534+
/// // When seeding both arguments at once the tangent return is the sum of both.
1535+
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
1536+
///
1537+
/// let mut out = 0.0;
1538+
/// let mut dout = 0.0;
1539+
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
1540+
/// // (out, dout) == (400.0, -400.0)
1541+
/// }
1542+
/// ```
1543+
///
1544+
/// We might want to track how one input float affects one or more output floats. In this case,
1545+
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
1546+
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
1547+
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
1548+
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
1549+
/// more efficient if we have more output floats marked as `Dual` than input floats.
1550+
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
15021551
#[unstable(feature = "autodiff", issue = "124509")]
15031552
#[allow_internal_unstable(rustc_attrs)]
15041553
#[allow_internal_unstable(core_intrinsics)]
@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
15181567
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15191568
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15201569
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1570+
///
1571+
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
1572+
///
1573+
/// `Active` can be used for float scalar values.
1574+
/// If used on an input, a new float will be appended to the return tuple of the generated
1575+
/// function. If the function returns a float scalar, `Active` can be used for the return as
1576+
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
1577+
///
1578+
/// `Duplicated` can be used on references, raw pointers, or other indirect input
1579+
/// arguments. It creates a new shadow argument of the same type, following the original argument.
1580+
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
1581+
///
1582+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1583+
/// if we are not interested in computing the derivatives with respect to this argument.
1584+
///
1585+
/// ### Usage examples:
1586+
///
1587+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1588+
/// #![feature(autodiff)]
1589+
/// use std::autodiff::*;
1590+
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
1591+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1592+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1593+
/// }
1594+
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
1595+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1596+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1597+
/// }
1598+
///
1599+
/// fn main() {
1600+
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
1601+
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
1602+
/// let mut output2 = 0.0;
1603+
/// let mut seed = 1.0;
1604+
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
1605+
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
1606+
/// }
1607+
/// ```
1608+
///
1609+
///
1610+
/// We often want to track how one or more input floats affect one output float. This output can
1611+
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
1612+
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
1613+
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
1614+
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
1615+
/// shadow of the outputs ("seed") will be reset to zero.
1616+
/// If the function has more than one output float marked as active or duplicated, users might want to
1617+
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.
1618+
/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
1619+
/// inputs.
1620+
/// Reverse mode is generally more efficient if we have more active/duplicated input than
1621+
/// output floats.
1622+
///
1623+
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
15211624
#[unstable(feature = "autodiff", issue = "124509")]
15221625
#[allow_internal_unstable(rustc_attrs)]
15231626
#[allow_internal_unstable(core_intrinsics)]

‎library/std/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
126126
# a borrow error occurs
127127
debug_refcell = ["core/debug_refcell"]
128128

129+
llvm_enzyme = ["core/llvm_enzyme"]
129130

130131
# Enable std_detect features:
131132
std_detect_file_io = ["std_detect/std_detect_file_io"]

‎library/sysroot/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
3535
std_detect_file_io = ["std/std_detect_file_io"]
3636
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
3737
windows_raw_dylib = ["std/windows_raw_dylib"]
38+
llvm_enzyme = ["std/llvm_enzyme"]

‎src/bootstrap/src/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,10 @@ impl Build {
846846
features.insert("compiler-builtins-mem");
847847
}
848848

849+
ifself.config.llvm_enzyme{
850+
features.insert("llvm_enzyme");
851+
}
852+
849853
features.into_iter().collect::<Vec<_>>().join(" ")
850854
}
851855

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk · rust-lang/rust@3732c3c · GitHub
Skip to content

Commit 3732c3c

Browse files
authored
Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk
Start documenting autodiff activities Some initial documentation of the autodiff macros and usage examples
2 parents 714f1ce + f5892da commit 3732c3c

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

‎library/core/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ optimize_for_size = []
2323
# Make `RefCell` store additional debugging information, which is printed out when
2424
# a borrow error occurs
2525
debug_refcell = []
26+
llvm_enzyme = []
2627

2728
[lints.rust.unexpected_cfgs]
2829
level = "warn"
@@ -38,4 +39,6 @@ check-cfg = [
3839
'cfg(target_has_reliable_f16_math)',
3940
'cfg(target_has_reliable_f128)',
4041
'cfg(target_has_reliable_f128_math)',
42+
'cfg(llvm_enzyme)',
43+
4144
]

‎library/core/src/macros/mod.rs‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
14991499
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15001500
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15011501
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1502+
///
1503+
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
1504+
///
1505+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1506+
/// if we are not interested in computing the derivatives with respect to this argument.
1507+
///
1508+
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
1509+
/// indirect input arguments. It can also be used on a scalar float return value.
1510+
/// If used on a return value, the generated function will return a tuple of two float scalars.
1511+
/// If used on an input argument, a new shadow argument of the same type will be created,
1512+
/// directly following the original argument.
1513+
///
1514+
/// ### Usage examples:
1515+
///
1516+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1517+
/// #![feature(autodiff)]
1518+
/// use std::autodiff::*;
1519+
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
1520+
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
1521+
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
1522+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1523+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1524+
/// }
1525+
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
1526+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1527+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1528+
/// }
1529+
///
1530+
/// fn main() {
1531+
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
1532+
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
1533+
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
1534+
/// // When seeding both arguments at once the tangent return is the sum of both.
1535+
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
1536+
///
1537+
/// let mut out = 0.0;
1538+
/// let mut dout = 0.0;
1539+
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
1540+
/// // (out, dout) == (400.0, -400.0)
1541+
/// }
1542+
/// ```
1543+
///
1544+
/// We might want to track how one input float affects one or more output floats. In this case,
1545+
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
1546+
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
1547+
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
1548+
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
1549+
/// more efficient if we have more output floats marked as `Dual` than input floats.
1550+
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
15021551
#[unstable(feature = "autodiff", issue = "124509")]
15031552
#[allow_internal_unstable(rustc_attrs)]
15041553
#[allow_internal_unstable(core_intrinsics)]
@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
15181567
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15191568
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15201569
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1570+
///
1571+
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
1572+
///
1573+
/// `Active` can be used for float scalar values.
1574+
/// If used on an input, a new float will be appended to the return tuple of the generated
1575+
/// function. If the function returns a float scalar, `Active` can be used for the return as
1576+
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
1577+
///
1578+
/// `Duplicated` can be used on references, raw pointers, or other indirect input
1579+
/// arguments. It creates a new shadow argument of the same type, following the original argument.
1580+
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
1581+
///
1582+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1583+
/// if we are not interested in computing the derivatives with respect to this argument.
1584+
///
1585+
/// ### Usage examples:
1586+
///
1587+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1588+
/// #![feature(autodiff)]
1589+
/// use std::autodiff::*;
1590+
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
1591+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1592+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1593+
/// }
1594+
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
1595+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1596+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1597+
/// }
1598+
///
1599+
/// fn main() {
1600+
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
1601+
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
1602+
/// let mut output2 = 0.0;
1603+
/// let mut seed = 1.0;
1604+
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
1605+
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
1606+
/// }
1607+
/// ```
1608+
///
1609+
///
1610+
/// We often want to track how one or more input floats affect one output float. This output can
1611+
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
1612+
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
1613+
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
1614+
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
1615+
/// shadow of the outputs ("seed") will be reset to zero.
1616+
/// If the function has more than one output float marked as active or duplicated, users might want to
1617+
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.
1618+
/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
1619+
/// inputs.
1620+
/// Reverse mode is generally more efficient if we have more active/duplicated input than
1621+
/// output floats.
1622+
///
1623+
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
15211624
#[unstable(feature = "autodiff", issue = "124509")]
15221625
#[allow_internal_unstable(rustc_attrs)]
15231626
#[allow_internal_unstable(core_intrinsics)]

‎library/std/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
126126
# a borrow error occurs
127127
debug_refcell = ["core/debug_refcell"]
128128

129+
llvm_enzyme = ["core/llvm_enzyme"]
129130

130131
# Enable std_detect features:
131132
std_detect_file_io = ["std_detect/std_detect_file_io"]

‎library/sysroot/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
3535
std_detect_file_io = ["std/std_detect_file_io"]
3636
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
3737
windows_raw_dylib = ["std/windows_raw_dylib"]
38+
llvm_enzyme = ["std/llvm_enzyme"]

‎src/bootstrap/src/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,10 @@ impl Build {
846846
features.insert("compiler-builtins-mem");
847847
}
848848

849+
ifself.config.llvm_enzyme{
850+
features.insert("llvm_enzyme");
851+
}
852+
849853
features.into_iter().collect::<Vec<_>>().join(" ")
850854
}
851855

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk · rust-lang/rust@3732c3c · GitHub
Skip to content

Commit 3732c3c

Browse files
authored
Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk
Start documenting autodiff activities Some initial documentation of the autodiff macros and usage examples
2 parents 714f1ce + f5892da commit 3732c3c

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

‎library/core/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ optimize_for_size = []
2323
# Make `RefCell` store additional debugging information, which is printed out when
2424
# a borrow error occurs
2525
debug_refcell = []
26+
llvm_enzyme = []
2627

2728
[lints.rust.unexpected_cfgs]
2829
level = "warn"
@@ -38,4 +39,6 @@ check-cfg = [
3839
'cfg(target_has_reliable_f16_math)',
3940
'cfg(target_has_reliable_f128)',
4041
'cfg(target_has_reliable_f128_math)',
42+
'cfg(llvm_enzyme)',
43+
4144
]

‎library/core/src/macros/mod.rs‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
14991499
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15001500
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15011501
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1502+
///
1503+
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
1504+
///
1505+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1506+
/// if we are not interested in computing the derivatives with respect to this argument.
1507+
///
1508+
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
1509+
/// indirect input arguments. It can also be used on a scalar float return value.
1510+
/// If used on a return value, the generated function will return a tuple of two float scalars.
1511+
/// If used on an input argument, a new shadow argument of the same type will be created,
1512+
/// directly following the original argument.
1513+
///
1514+
/// ### Usage examples:
1515+
///
1516+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1517+
/// #![feature(autodiff)]
1518+
/// use std::autodiff::*;
1519+
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
1520+
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
1521+
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
1522+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1523+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1524+
/// }
1525+
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
1526+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1527+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1528+
/// }
1529+
///
1530+
/// fn main() {
1531+
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
1532+
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
1533+
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
1534+
/// // When seeding both arguments at once the tangent return is the sum of both.
1535+
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
1536+
///
1537+
/// let mut out = 0.0;
1538+
/// let mut dout = 0.0;
1539+
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
1540+
/// // (out, dout) == (400.0, -400.0)
1541+
/// }
1542+
/// ```
1543+
///
1544+
/// We might want to track how one input float affects one or more output floats. In this case,
1545+
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
1546+
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
1547+
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
1548+
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
1549+
/// more efficient if we have more output floats marked as `Dual` than input floats.
1550+
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
15021551
#[unstable(feature = "autodiff", issue = "124509")]
15031552
#[allow_internal_unstable(rustc_attrs)]
15041553
#[allow_internal_unstable(core_intrinsics)]
@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
15181567
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15191568
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15201569
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1570+
///
1571+
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
1572+
///
1573+
/// `Active` can be used for float scalar values.
1574+
/// If used on an input, a new float will be appended to the return tuple of the generated
1575+
/// function. If the function returns a float scalar, `Active` can be used for the return as
1576+
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
1577+
///
1578+
/// `Duplicated` can be used on references, raw pointers, or other indirect input
1579+
/// arguments. It creates a new shadow argument of the same type, following the original argument.
1580+
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
1581+
///
1582+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1583+
/// if we are not interested in computing the derivatives with respect to this argument.
1584+
///
1585+
/// ### Usage examples:
1586+
///
1587+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1588+
/// #![feature(autodiff)]
1589+
/// use std::autodiff::*;
1590+
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
1591+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1592+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1593+
/// }
1594+
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
1595+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1596+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1597+
/// }
1598+
///
1599+
/// fn main() {
1600+
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
1601+
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
1602+
/// let mut output2 = 0.0;
1603+
/// let mut seed = 1.0;
1604+
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
1605+
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
1606+
/// }
1607+
/// ```
1608+
///
1609+
///
1610+
/// We often want to track how one or more input floats affect one output float. This output can
1611+
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
1612+
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
1613+
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
1614+
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
1615+
/// shadow of the outputs ("seed") will be reset to zero.
1616+
/// If the function has more than one output float marked as active or duplicated, users might want to
1617+
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.
1618+
/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
1619+
/// inputs.
1620+
/// Reverse mode is generally more efficient if we have more active/duplicated input than
1621+
/// output floats.
1622+
///
1623+
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
15211624
#[unstable(feature = "autodiff", issue = "124509")]
15221625
#[allow_internal_unstable(rustc_attrs)]
15231626
#[allow_internal_unstable(core_intrinsics)]

‎library/std/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
126126
# a borrow error occurs
127127
debug_refcell = ["core/debug_refcell"]
128128

129+
llvm_enzyme = ["core/llvm_enzyme"]
129130

130131
# Enable std_detect features:
131132
std_detect_file_io = ["std_detect/std_detect_file_io"]

‎library/sysroot/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
3535
std_detect_file_io = ["std/std_detect_file_io"]
3636
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
3737
windows_raw_dylib = ["std/windows_raw_dylib"]
38+
llvm_enzyme = ["std/llvm_enzyme"]

‎src/bootstrap/src/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,10 @@ impl Build {
846846
features.insert("compiler-builtins-mem");
847847
}
848848

849+
ifself.config.llvm_enzyme{
850+
features.insert("llvm_enzyme");
851+
}
852+
849853
features.into_iter().collect::<Vec<_>>().join(" ")
850854
}
851855

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk · rust-lang/rust@3732c3c · GitHub
Skip to content

Commit 3732c3c

Browse files
authored
Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk
Start documenting autodiff activities Some initial documentation of the autodiff macros and usage examples
2 parents 714f1ce + f5892da commit 3732c3c

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

‎library/core/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ optimize_for_size = []
2323
# Make `RefCell` store additional debugging information, which is printed out when
2424
# a borrow error occurs
2525
debug_refcell = []
26+
llvm_enzyme = []
2627

2728
[lints.rust.unexpected_cfgs]
2829
level = "warn"
@@ -38,4 +39,6 @@ check-cfg = [
3839
'cfg(target_has_reliable_f16_math)',
3940
'cfg(target_has_reliable_f128)',
4041
'cfg(target_has_reliable_f128_math)',
42+
'cfg(llvm_enzyme)',
43+
4144
]

‎library/core/src/macros/mod.rs‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
14991499
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15001500
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15011501
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1502+
///
1503+
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
1504+
///
1505+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1506+
/// if we are not interested in computing the derivatives with respect to this argument.
1507+
///
1508+
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
1509+
/// indirect input arguments. It can also be used on a scalar float return value.
1510+
/// If used on a return value, the generated function will return a tuple of two float scalars.
1511+
/// If used on an input argument, a new shadow argument of the same type will be created,
1512+
/// directly following the original argument.
1513+
///
1514+
/// ### Usage examples:
1515+
///
1516+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1517+
/// #![feature(autodiff)]
1518+
/// use std::autodiff::*;
1519+
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
1520+
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
1521+
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
1522+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1523+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1524+
/// }
1525+
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
1526+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1527+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1528+
/// }
1529+
///
1530+
/// fn main() {
1531+
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
1532+
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
1533+
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
1534+
/// // When seeding both arguments at once the tangent return is the sum of both.
1535+
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
1536+
///
1537+
/// let mut out = 0.0;
1538+
/// let mut dout = 0.0;
1539+
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
1540+
/// // (out, dout) == (400.0, -400.0)
1541+
/// }
1542+
/// ```
1543+
///
1544+
/// We might want to track how one input float affects one or more output floats. In this case,
1545+
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
1546+
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
1547+
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
1548+
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
1549+
/// more efficient if we have more output floats marked as `Dual` than input floats.
1550+
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
15021551
#[unstable(feature = "autodiff", issue = "124509")]
15031552
#[allow_internal_unstable(rustc_attrs)]
15041553
#[allow_internal_unstable(core_intrinsics)]
@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
15181567
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15191568
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15201569
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1570+
///
1571+
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
1572+
///
1573+
/// `Active` can be used for float scalar values.
1574+
/// If used on an input, a new float will be appended to the return tuple of the generated
1575+
/// function. If the function returns a float scalar, `Active` can be used for the return as
1576+
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
1577+
///
1578+
/// `Duplicated` can be used on references, raw pointers, or other indirect input
1579+
/// arguments. It creates a new shadow argument of the same type, following the original argument.
1580+
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
1581+
///
1582+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1583+
/// if we are not interested in computing the derivatives with respect to this argument.
1584+
///
1585+
/// ### Usage examples:
1586+
///
1587+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1588+
/// #![feature(autodiff)]
1589+
/// use std::autodiff::*;
1590+
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
1591+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1592+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1593+
/// }
1594+
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
1595+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1596+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1597+
/// }
1598+
///
1599+
/// fn main() {
1600+
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
1601+
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
1602+
/// let mut output2 = 0.0;
1603+
/// let mut seed = 1.0;
1604+
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
1605+
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
1606+
/// }
1607+
/// ```
1608+
///
1609+
///
1610+
/// We often want to track how one or more input floats affect one output float. This output can
1611+
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
1612+
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
1613+
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
1614+
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
1615+
/// shadow of the outputs ("seed") will be reset to zero.
1616+
/// If the function has more than one output float marked as active or duplicated, users might want to
1617+
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.
1618+
/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
1619+
/// inputs.
1620+
/// Reverse mode is generally more efficient if we have more active/duplicated input than
1621+
/// output floats.
1622+
///
1623+
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
15211624
#[unstable(feature = "autodiff", issue = "124509")]
15221625
#[allow_internal_unstable(rustc_attrs)]
15231626
#[allow_internal_unstable(core_intrinsics)]

‎library/std/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
126126
# a borrow error occurs
127127
debug_refcell = ["core/debug_refcell"]
128128

129+
llvm_enzyme = ["core/llvm_enzyme"]
129130

130131
# Enable std_detect features:
131132
std_detect_file_io = ["std_detect/std_detect_file_io"]

‎library/sysroot/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
3535
std_detect_file_io = ["std/std_detect_file_io"]
3636
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
3737
windows_raw_dylib = ["std/windows_raw_dylib"]
38+
llvm_enzyme = ["std/llvm_enzyme"]

‎src/bootstrap/src/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,10 @@ impl Build {
846846
features.insert("compiler-builtins-mem");
847847
}
848848

849+
ifself.config.llvm_enzyme{
850+
features.insert("llvm_enzyme");
851+
}
852+
849853
features.into_iter().collect::<Vec<_>>().join(" ")
850854
}
851855

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk · rust-lang/rust@3732c3c · GitHub
Skip to content

Commit 3732c3c

Browse files
authored
Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk
Start documenting autodiff activities Some initial documentation of the autodiff macros and usage examples
2 parents 714f1ce + f5892da commit 3732c3c

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

‎library/core/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ optimize_for_size = []
2323
# Make `RefCell` store additional debugging information, which is printed out when
2424
# a borrow error occurs
2525
debug_refcell = []
26+
llvm_enzyme = []
2627

2728
[lints.rust.unexpected_cfgs]
2829
level = "warn"
@@ -38,4 +39,6 @@ check-cfg = [
3839
'cfg(target_has_reliable_f16_math)',
3940
'cfg(target_has_reliable_f128)',
4041
'cfg(target_has_reliable_f128_math)',
42+
'cfg(llvm_enzyme)',
43+
4144
]

‎library/core/src/macros/mod.rs‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
14991499
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15001500
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15011501
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1502+
///
1503+
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
1504+
///
1505+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1506+
/// if we are not interested in computing the derivatives with respect to this argument.
1507+
///
1508+
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
1509+
/// indirect input arguments. It can also be used on a scalar float return value.
1510+
/// If used on a return value, the generated function will return a tuple of two float scalars.
1511+
/// If used on an input argument, a new shadow argument of the same type will be created,
1512+
/// directly following the original argument.
1513+
///
1514+
/// ### Usage examples:
1515+
///
1516+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1517+
/// #![feature(autodiff)]
1518+
/// use std::autodiff::*;
1519+
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
1520+
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
1521+
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
1522+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1523+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1524+
/// }
1525+
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
1526+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1527+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1528+
/// }
1529+
///
1530+
/// fn main() {
1531+
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
1532+
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
1533+
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
1534+
/// // When seeding both arguments at once the tangent return is the sum of both.
1535+
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
1536+
///
1537+
/// let mut out = 0.0;
1538+
/// let mut dout = 0.0;
1539+
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
1540+
/// // (out, dout) == (400.0, -400.0)
1541+
/// }
1542+
/// ```
1543+
///
1544+
/// We might want to track how one input float affects one or more output floats. In this case,
1545+
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
1546+
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
1547+
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
1548+
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
1549+
/// more efficient if we have more output floats marked as `Dual` than input floats.
1550+
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
15021551
#[unstable(feature = "autodiff", issue = "124509")]
15031552
#[allow_internal_unstable(rustc_attrs)]
15041553
#[allow_internal_unstable(core_intrinsics)]
@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
15181567
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15191568
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15201569
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1570+
///
1571+
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
1572+
///
1573+
/// `Active` can be used for float scalar values.
1574+
/// If used on an input, a new float will be appended to the return tuple of the generated
1575+
/// function. If the function returns a float scalar, `Active` can be used for the return as
1576+
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
1577+
///
1578+
/// `Duplicated` can be used on references, raw pointers, or other indirect input
1579+
/// arguments. It creates a new shadow argument of the same type, following the original argument.
1580+
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
1581+
///
1582+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1583+
/// if we are not interested in computing the derivatives with respect to this argument.
1584+
///
1585+
/// ### Usage examples:
1586+
///
1587+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1588+
/// #![feature(autodiff)]
1589+
/// use std::autodiff::*;
1590+
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
1591+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1592+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1593+
/// }
1594+
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
1595+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1596+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1597+
/// }
1598+
///
1599+
/// fn main() {
1600+
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
1601+
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
1602+
/// let mut output2 = 0.0;
1603+
/// let mut seed = 1.0;
1604+
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
1605+
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
1606+
/// }
1607+
/// ```
1608+
///
1609+
///
1610+
/// We often want to track how one or more input floats affect one output float. This output can
1611+
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
1612+
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
1613+
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
1614+
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
1615+
/// shadow of the outputs ("seed") will be reset to zero.
1616+
/// If the function has more than one output float marked as active or duplicated, users might want to
1617+
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.
1618+
/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
1619+
/// inputs.
1620+
/// Reverse mode is generally more efficient if we have more active/duplicated input than
1621+
/// output floats.
1622+
///
1623+
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
15211624
#[unstable(feature = "autodiff", issue = "124509")]
15221625
#[allow_internal_unstable(rustc_attrs)]
15231626
#[allow_internal_unstable(core_intrinsics)]

‎library/std/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
126126
# a borrow error occurs
127127
debug_refcell = ["core/debug_refcell"]
128128

129+
llvm_enzyme = ["core/llvm_enzyme"]
129130

130131
# Enable std_detect features:
131132
std_detect_file_io = ["std_detect/std_detect_file_io"]

‎library/sysroot/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
3535
std_detect_file_io = ["std/std_detect_file_io"]
3636
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
3737
windows_raw_dylib = ["std/windows_raw_dylib"]
38+
llvm_enzyme = ["std/llvm_enzyme"]

‎src/bootstrap/src/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,10 @@ impl Build {
846846
features.insert("compiler-builtins-mem");
847847
}
848848

849+
ifself.config.llvm_enzyme{
850+
features.insert("llvm_enzyme");
851+
}
852+
849853
features.into_iter().collect::<Vec<_>>().join(" ")
850854
}
851855

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk · rust-lang/rust@3732c3c · GitHub
Skip to content

Commit 3732c3c

Browse files
authored
Rollup merge of #148201 - ZuseZ4:autodiff-activity-docs, r=oli-obk
Start documenting autodiff activities Some initial documentation of the autodiff macros and usage examples
2 parents 714f1ce + f5892da commit 3732c3c

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

‎library/core/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ optimize_for_size = []
2323
# Make `RefCell` store additional debugging information, which is printed out when
2424
# a borrow error occurs
2525
debug_refcell = []
26+
llvm_enzyme = []
2627

2728
[lints.rust.unexpected_cfgs]
2829
level = "warn"
@@ -38,4 +39,6 @@ check-cfg = [
3839
'cfg(target_has_reliable_f16_math)',
3940
'cfg(target_has_reliable_f128)',
4041
'cfg(target_has_reliable_f128_math)',
42+
'cfg(llvm_enzyme)',
43+
4144
]

‎library/core/src/macros/mod.rs‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
14991499
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15001500
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15011501
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1502+
///
1503+
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
1504+
///
1505+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1506+
/// if we are not interested in computing the derivatives with respect to this argument.
1507+
///
1508+
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
1509+
/// indirect input arguments. It can also be used on a scalar float return value.
1510+
/// If used on a return value, the generated function will return a tuple of two float scalars.
1511+
/// If used on an input argument, a new shadow argument of the same type will be created,
1512+
/// directly following the original argument.
1513+
///
1514+
/// ### Usage examples:
1515+
///
1516+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1517+
/// #![feature(autodiff)]
1518+
/// use std::autodiff::*;
1519+
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
1520+
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
1521+
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
1522+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1523+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1524+
/// }
1525+
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
1526+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1527+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1528+
/// }
1529+
///
1530+
/// fn main() {
1531+
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
1532+
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
1533+
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
1534+
/// // When seeding both arguments at once the tangent return is the sum of both.
1535+
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
1536+
///
1537+
/// let mut out = 0.0;
1538+
/// let mut dout = 0.0;
1539+
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
1540+
/// // (out, dout) == (400.0, -400.0)
1541+
/// }
1542+
/// ```
1543+
///
1544+
/// We might want to track how one input float affects one or more output floats. In this case,
1545+
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
1546+
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
1547+
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
1548+
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
1549+
/// more efficient if we have more output floats marked as `Dual` than input floats.
1550+
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
15021551
#[unstable(feature = "autodiff", issue = "124509")]
15031552
#[allow_internal_unstable(rustc_attrs)]
15041553
#[allow_internal_unstable(core_intrinsics)]
@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
15181567
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
15191568
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
15201569
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
1570+
///
1571+
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
1572+
///
1573+
/// `Active` can be used for float scalar values.
1574+
/// If used on an input, a new float will be appended to the return tuple of the generated
1575+
/// function. If the function returns a float scalar, `Active` can be used for the return as
1576+
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
1577+
///
1578+
/// `Duplicated` can be used on references, raw pointers, or other indirect input
1579+
/// arguments. It creates a new shadow argument of the same type, following the original argument.
1580+
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
1581+
///
1582+
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
1583+
/// if we are not interested in computing the derivatives with respect to this argument.
1584+
///
1585+
/// ### Usage examples:
1586+
///
1587+
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
1588+
/// #![feature(autodiff)]
1589+
/// use std::autodiff::*;
1590+
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
1591+
/// fn rosenbrock(x: f64, y: f64) -> f64 {
1592+
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
1593+
/// }
1594+
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
1595+
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
1596+
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
1597+
/// }
1598+
///
1599+
/// fn main() {
1600+
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
1601+
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
1602+
/// let mut output2 = 0.0;
1603+
/// let mut seed = 1.0;
1604+
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
1605+
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
1606+
/// }
1607+
/// ```
1608+
///
1609+
///
1610+
/// We often want to track how one or more input floats affect one output float. This output can
1611+
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
1612+
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
1613+
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
1614+
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
1615+
/// shadow of the outputs ("seed") will be reset to zero.
1616+
/// If the function has more than one output float marked as active or duplicated, users might want to
1617+
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.
1618+
/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
1619+
/// inputs.
1620+
/// Reverse mode is generally more efficient if we have more active/duplicated input than
1621+
/// output floats.
1622+
///
1623+
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
15211624
#[unstable(feature = "autodiff", issue = "124509")]
15221625
#[allow_internal_unstable(rustc_attrs)]
15231626
#[allow_internal_unstable(core_intrinsics)]

‎library/std/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
126126
# a borrow error occurs
127127
debug_refcell = ["core/debug_refcell"]
128128

129+
llvm_enzyme = ["core/llvm_enzyme"]
129130

130131
# Enable std_detect features:
131132
std_detect_file_io = ["std_detect/std_detect_file_io"]

‎library/sysroot/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
3535
std_detect_file_io = ["std/std_detect_file_io"]
3636
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
3737
windows_raw_dylib = ["std/windows_raw_dylib"]
38+
llvm_enzyme = ["std/llvm_enzyme"]

‎src/bootstrap/src/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,10 @@ impl Build {
846846
features.insert("compiler-builtins-mem");
847847
}
848848

849+
ifself.config.llvm_enzyme{
850+
features.insert("llvm_enzyme");
851+
}
852+
849853
features.into_iter().collect::<Vec<_>>().join(" ")
850854
}
851855

0 commit comments

Comments
 (0)