Skip to content

Conversation

@da-roth
Copy link
Contributor

@da-roth da-roth commented Dec 19, 2025

Comments regarding the discussion in #70 (comment)

Regarding your XAD integration points:

Zero overhead when JIT is not wanted: I’ve added a compile-time CMake option XAD_ENABLE_JIT (default OFF). When it’s OFF, the JIT-related headers and code paths are not compiled/installed, and all JIT-specific logic is behind #ifdef XAD_ENABLE_JIT. Concretely, the JIT headers are only added to public_headers when enabled, and the main include XAD.hpp only includes JIT headers under the same flag.

I also modified the benchmark workflow that compares the same codebase built with XAD_ENABLE_JIT=OFF vs ON to quantify any compile-time-flag overhead.

Backend factory / configuration ergonomics: I implemented JITCompiler::setBackend(std::unique_ptr) (and a constructor taking std::unique_ptr), so users can supply backends with arbitrary constructor parameters/configuration and retain full control (move ownership into XAD). If you prefer the std::forward-style factory API as well, I can add that on top, but the unique_ptr setter seemed like the simplest flexible baseline.

Tests / coverage: I’ve added dedicated JIT tests (JIT_test.cpp, ExpressionMathJit_test.cpp) and extended test helpers with JIT-specific helpers.

On CI: I updated the main CI workflow to build/test with XAD_ENABLE_JIT=ON, and added a separate CI workflow that validates XAD_ENABLE_JIT=OFF to ensure the “no-JIT” configuration stays clean.

PR description:

New files added

  • .github/workflows/benchmarks-jit-on-off.yml: Checks out the PR once, builds it twice (XAD_ENABLE_JIT=OFF vs XAD_ENABLE_JIT=ON), runs samples/LiborSwaptionPricer for both builds, and posts a PR comment comparing timings (this measures the impact of the compile-time flag; it does not necessarily exercise runtime JIT unless the sample activates JIT).

  • .github/workflows/ci-jit-off.yml: Dedicated workflow that builds/tests with XAD_ENABLE_JIT=OFF (to validate “JIT disabled” configuration).

  • src/XAD/JITGraph.hpp: Defines JITOpCode plus the JITGraph data structure (nodes, operands, constants, inputs/outputs).

  • src/XAD/JITBackendInterface.hpp: Defines IJITBackend interface for pluggable graph execution backends.

  • src/XAD/JITGraphInterpreter.hpp: Reference backend implementing IJITBackend by interpreting the JITGraph (forward + backward).

  • src/XAD/JITOpCodeTraits.hpp: Maps existing XAD operator/functor types to JITOpCode values.

  • src/XAD/JITExprTraits.hpp: Helper traits/utilities for recording expressions into a JITGraph (e.g., constants, scalar-constant ops, ldexp handling).

  • src/XAD/JITCompiler.hpp: JIT “tape-like” recorder/executor: tracks inputs/outputs, records expression graphs, compiles via backend, supports forward/backward evaluation.

  • src/XAD/ABool.hpp: Trackable boolean helper for JIT-recorded comparisons/conditionals (records compare nodes and supports If(trueVal,falseVal) selection).

  • test/JIT_test.cpp: Unit tests for JITCompiler lifecycle, recording/compile/forward/backward behavior, backend swapping, etc. (compiled when XAD_ENABLE_JIT=ON).

  • test/ExpressionMathJit_test.cpp: JIT-focused math operation tests (compiled when XAD_ENABLE_JIT=ON).

Existing files modified

  • .github/workflows/ci.yml: Main CI configures builds with -DXAD_ENABLE_JIT=ON (i.e. the PR path is validated in CI with JIT compiled in). A separate workflow (ci-jit-off.yml) validates XAD_ENABLE_JIT=OFF.

  • cmake/XADSetupOptions.cmake: Adds CMake option XAD_ENABLE_JIT (default OFF) and a status message when enabled.

  • src/CMakeLists.txt: Adds the new JIT headers to public_headers only when XAD_ENABLE_JIT is enabled.

  • src/XAD/Config.hpp.in: Adds #cmakedefine XAD_ENABLE_JIT to generate the compile-time flag in Config.hpp.

  • src/XAD/XAD.hpp: When XAD_ENABLE_JIT is enabled, includes the JIT public headers (JITCompiler.hpp, ABool.hpp).

  • src/XAD/BinaryExpr.hpp: When XAD_ENABLE_JIT is enabled, adds recordJIT(JITGraph&) so binary expressions can record themselves into a JITGraph.

  • src/XAD/UnaryExpr.hpp: When XAD_ENABLE_JIT is enabled, adds recordJIT(JITGraph&) so unary expressions can record themselves into a JITGraph, including dispatch for:

    • plain unary ops
    • unary ops with scalar constants
    • ldexp-style ops using an “immediate” exponent
  • src/XAD/UnaryOperators.hpp: Adds JIT-only includes (guarded by XAD_ENABLE_JIT) needed for JIT comparison/conditional support.

  • src/XAD/Literals.hpp: Integrates JIT into AReal literal type:

    • Adds JIT-only includes and helpers so AReal can participate in graph recording.
    • Adds recordJIT(JITGraph&) for literals/AD variables and plumbing so expression construction/assignment can record to an active JIT graph when there is no active tape and a JITCompiler is active.
    • Restricts JIT derivative access to the supported configuration (Scalar == nested_type) and avoids instantiating the JIT derivative path for higher-order AD types.
  • test/CMakeLists.txt: Adds JIT tests (JIT_test.cpp, ExpressionMathJit_test.cpp) only when XAD_ENABLE_JIT is enabled.

  • test/TestHelpers.hpp: Adds JIT-only helper functions (mathTest_jit, mathTest2_jit) used by the new JIT math tests.

Copy link
Collaborator

@auto-differentiation-dev auto-differentiation-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this - it’s very close now. There are just a few minor comments left to address.

If you have a chance, it would be great to have the new JIT feature reflected in the README.md in whatever way you think fits best. Given the scope of your contribution and the fact that it will likely bump XAD to version 2.0, this might be a good opportunity to adjust the README more broadly if you feel it makes sense.

Copy link
Contributor Author

@da-roth da-roth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback! I hope I addressed all the comments (also updated the PR in the docs).

Regarding the README:

  • Added JIT Backend Support to Key Features

Also in a seperate commit (afa12b62784e3289e4f61f2ee243915804ae883a9), I added

  • Added xad-forge to related projects — which provides the forge-based JIT backends as a separate repository (the one that can be used later in quantlib-risks-cpp).
    Let me know if you'd prefer to not mention it here - I wouldn't really mind if not. If so, I'd just revert that commit.

Copy link
Collaborator

@auto-differentiation-dev auto-differentiation-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the updates, everything looks great now 👍

The README changes make sense, including the mention of xad-forge, so no need to revert that commit.

We're very happy with where this landed and will go ahead and merge the PR. Thanks again for the solid contribution.

Feel free to open a PR on QuantLib-Risks-Cpp when you're ready. We'll be glad to help there in any way we can.

@auto-differentiation-dev auto-differentiation-dev merged commit 55b9084 into auto-differentiation:main Dec 30, 2025
141 checks passed
@boring-cyborg
Copy link

boring-cyborg bot commented Dec 30, 2025

Awesome work, congrats on your first merged pull request!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants