MatLogica | AADC Debugging & Troubleshooting Guide

AADC Debugging & Troubleshooting Guide

AADC Debugging & Troubleshooting: Ensure Perfect Numerical Accuracy

Master AADC's comprehensive debugging toolkit to detect numerical differences, verify branch coverage, understand floating-point behavior, and ensure flawless integration of automatic differentiation in your quantitative finance code.

Comprehensive Debugging for Flawless Integration

AADC's advanced debugging and diagnostics toolkits ensure that your integration maintains perfect numerical accuracy while maximizing performance. This guide covers the essential tools and techniques for identifying and resolving issues during AADC integration.

What You'll Learn

  • Numerical Difference Detection
  • Branch Coverage Analysis
  • Floating-Point Arithmetic Deep Dive
  • Diagnostics Toolkit Mastery

Numerical Difference Detection

Pinpoint exact sources of numerical mismatches

Understanding Numerical Differences

In most cases, AADC produces results that are bit-for-bit identical to your original code. However, in some instances, you may observe small numerical differences. These differences are not errors—they result from legitimate compiler optimizations that AADC's JIT compiler performs to maximize performance.

Why Differences Occur

AADC's JIT compiler may reorder floating-point operations for better vectorization and performance. While mathematically equivalent, different operation orders can produce slightly different results due to floating-point arithmetic properties. For example, (a + b) + c may yield a different result than a + (b + c) in finite-precision arithmetic.

The Debugging Toolkit

AADC's debugging toolkit provides line-by-line identification of where numerical differences arise. This allows you to:

✓ Capabilities

  • Identify exact code location of differences
  • Compare original vs. optimized values
  • Analyze operation reordering effects
  • Track numerical precision loss
  • Validate acceptable tolerance ranges

⚡ Benefits

  • Immediate mismatch detection
  • Confident resolution of differences
  • Verification of numerical stability
  • Documentation of acceptable variances
  • Accelerated integration validation

Using the Numerical Difference Detector

The debugging workflow involves three main steps:

Step 1: Enable Debug Mode

Configure the AADC context to track numerical differences during execution. You can set specific tolerance thresholds to define what constitutes an acceptable difference for your application.

Step 2: Run Comparison

Execute your kernel with debug information enabled. The system automatically compares results from the optimized kernel against the original implementation, tracking every intermediate value throughout the computation.

Step 3: Analyze Report

Review the detailed difference report that identifies the exact file and line number where differences occur, shows both original and optimized values, calculates the magnitude and percentage of difference, explains the cause (such as operation reordering), and provides a status indicating whether the difference is within acceptable tolerance.

Resolution Strategies

  • Accept the difference: Most differences are negligible and within acceptable tolerance
  • Adjust tolerance: Set appropriate tolerance levels based on your application requirements
  • Force operation order: Use hints to preserve specific operation sequences if needed
  • Document findings: Keep records of acceptable variances for validation purposes

Common Scenarios and Solutions

Scenario Typical Difference Resolution
Sum Accumulation 1e-13 to 1e-15 Accept - reordering improves vectorization
Complex Exponentials 1e-14 to 1e-16 Accept - mathematically equivalent
Division Chains 1e-12 to 1e-14 Accept or adjust tolerance threshold
Trigonometric Functions 1e-15 to 1e-17 Accept - within floating-point precision
Large Magnitude Differences > 1e-6 Investigate - may indicate integration issue

Branch Coverage Analysis

Ensure all code paths are correctly handled

Why Branch Coverage Matters

In stochastic models and path-dependent derivatives pricing, your code often contains conditional branches based on runtime values. For AADC to generate accurate kernels that handle automatic differentiation correctly, all possible branches must be recorded during the kernel generation phase.

⚠️ The Branch Coverage Problem

If you record your function with a single execution path, AADC may only capture one branch of an if-statement. When the kernel later encounters the other branch, it may produce incorrect results or fail to compute derivatives properly. This is especially critical for barrier options, path-dependent payoffs, and early exercise features.

Example: Barrier Option Problem

The Challenge

Consider a barrier option function that checks if the spot price exceeds a barrier level. If the barrier is breached, the option knocks out and returns zero. Otherwise, it calculates the normal payoff.

Problem: If you record with a spot price below the barrier (e.g., spot = 95, barrier = 100), only the "option still alive" branch is recorded. Later executions with spot prices above the barrier (e.g., spot = 105) will use an incorrect computation graph because the knock-out branch was never recorded!

The Diagnostics Toolkit Solution

AADC's Diagnostics Toolkit automatically detects incomplete branch coverage and flags any code sections where branches are not properly recorded. This ensures robust automatic differentiation across all possible execution paths.

Using Branch Coverage Analysis

Step 1: Enable Branch Analysis

Configure the AADC context to track which branches are executed during recording. You can set the analysis mode to comprehensive, which provides detailed information about every conditional statement encountered.

Step 2: Record Multiple Scenarios

To ensure complete branch coverage, record your function multiple times with different input values that trigger different conditional paths. For the barrier option example, you would record once with the spot price below the barrier and again with the spot price above the barrier. AADC can merge these multiple recordings into a single kernel that handles all branches correctly.

Step 3: Review Branch Coverage Report

After recording, retrieve the branch coverage report to verify completeness. The report identifies any branches that were not covered during recording, showing the filename, line number, branch description, and suggestions for additional test scenarios needed to achieve complete coverage.

✓ Best Practices for Branch Coverage

  • Record with diverse inputs: Use representative scenarios covering all conditional paths
  • Test boundary conditions: Record with values that trigger all if-statement branches
  • Use multi-scenario recording: AADC can merge multiple executions into a single kernel
  • Review coverage reports: Always check the diagnostics output before production use
  • Document branch scenarios: Keep records of which scenarios were used for recording

Advanced: Multi-Path Recording

Automatic Branch Exploration: AADC provides an advanced feature that can automatically explore different branches during recording. When enabled, the system intelligently tests multiple code paths without requiring you to manually specify different scenarios. This ensures complete branch coverage and generates a kernel capable of correctly handling all conditional paths encountered in your pricing function, including complex path-dependent options with multiple barriers, strikes, dates, and stochastic conditions.

Branch Coverage Checklist

Check What to Verify
✓ If-Statements Both true and false branches recorded
✓ Switch-Case All case branches covered
✓ Barrier Conditions Above and below barrier scenarios
✓ Early Exercise Both exercise and continuation paths
✓ Knockout Events Knockout and survival scenarios
✓ Path Dependency All possible path outcomes

Floating-Point Rounding Explained

Understanding the mathematics behind numerical differences

The Nature of Floating-Point Arithmetic

Floating-point numbers on computers use finite precision to represent real numbers. This fundamental limitation means that even mathematically equivalent expressions can produce different results depending on the order of operations.

📊 Floating-Point Representation (IEEE 754)

A double-precision number uses 64 bits:

  • 1 bit: Sign
  • 11 bits: Exponent
  • 52 bits: Mantissa (significand)

This provides approximately 15-17 decimal digits of precision, but not all decimal numbers can be exactly represented.

Why Operation Order Matters

Consider the expression (a + b) + c. Mathematically, this equals a + (b + c). However, in finite-precision arithmetic, the results can differ:

Demonstration: Large Number with Small Numbers

Scenario: Adding a very large number (1.0e16), a small number (1.0), and the negative of the large number (-1.0e16).

Left-to-right evaluation: First adds the large number and small number. Due to floating-point precision limits, the small number gets lost in the addition (1.0e16 + 1.0 = 1.0e16 in finite precision). Then adding the negative large number results in 0.0.

Right-to-left evaluation: First adds the small number with the negative large number, which involves different rounding. The order of operations affects the final result, potentially preserving the small number through a different calculation path, resulting in 1.0.

Result: The two evaluation orders produce different results (0.0 vs 1.0) despite mathematical equivalence! This demonstrates how operation order matters in finite-precision arithmetic.

Common Rounding Scenarios in Financial Calculations

Sum Accumulation

When accumulating many small values (e.g., Monte Carlo paths), the order in which values are added affects the final sum. Iterating through paths and adding each payoff sequentially can produce different results than adding them in a different order, even though mathematically they should be identical.

Compound Operations

Expressions with multiple operations can be reordered for performance. For example, in option pricing formulas involving spot price, exponentials of rate and volatility terms, and payoff calculations, the JIT compiler may reorder multiplications to optimize instruction pipelining, leading to slightly different rounding behavior.

Division Chains

Multiple divisions amplify rounding errors. Performing sequential divisions (dividing by one number, then another, then another) produces different results than dividing by the product of all divisors in a single operation. The sequential approach accumulates more rounding errors at each step.

Fused Operations

FMA (fused multiply-add) preserves precision by performing multiplication and addition in a single operation with only one rounding step. Traditional approaches perform multiplication first (with rounding), then addition (with another rounding), resulting in two rounding errors. FMA is more accurate with only one rounding step.

AADC's Optimization Impact

AADC's JIT compiler applies several optimizations that can change operation order:

Optimization Impact on Rounding Typical Difference
Vectorization Processes 4-8 values simultaneously, may change accumulation order 1e-14 to 1e-16
Expression Reordering Rearranges operations for better instruction pipelining 1e-13 to 1e-15
Common Subexpression Elimination Reuses computed values, changes evaluation order 1e-15 to 1e-17
Fused Operations Uses FMA instructions for better precision Actually improves accuracy!
Parallel Reduction Multi-threaded accumulation uses different reduction trees 1e-12 to 1e-14

✓ Why These Differences Are Acceptable

  • Mathematically equivalent: All optimizations preserve mathematical correctness
  • Within precision limits: Differences are at the limit of double precision (1e-15)
  • Consistent and reproducible: AADC kernels produce identical results across runs
  • Financially insignificant: Differences far below typical bid-ask spreads
  • Better than alternatives: Often more accurate due to FMA and reduced operations

Setting Appropriate Tolerances

Recommended Tolerance Configurations

For typical financial calculations (option pricing, Greeks computation): Use absolute tolerance around 1e-10 and relative tolerance around 1e-8. These settings work well for most derivatives pricing applications.

For high-precision requirements (arbitrage detection, regulatory calculations): Tighten tolerances to 1e-12 absolute and 1e-10 relative to catch even smaller discrepancies.

For production validation (regression testing against existing systems): Use looser tolerances like 1e-6 absolute and 1e-5 relative to account for real-world numerical variability while still catching meaningful differences.

Understanding Tolerance Metrics

AADC provides multiple ways to measure numerical differences, each offering different perspectives on accuracy:

Available Metrics

Absolute Difference: The raw numerical difference between original and optimized values, calculated as the absolute value of (original - optimized). For example, if original is 102.3456789 and optimized is 102.3456792, the absolute difference is 3e-7.

Relative Difference: The difference as a percentage of the original value, calculated as absolute difference divided by the original value. Using the same example, 3e-7 / 102.3456789 = 2.9e-9, which is 0.0000003%. This metric is useful for understanding the proportional significance of differences.

ULP (Units in the Last Place): Counts the number of representable floating-point values between the two numbers. This provides a hardware-level view of precision, measuring how many discrete floating-point steps separate the values.

Statistical Significance (for Monte Carlo): For stochastic calculations, tests whether the difference is within the expected statistical noise of the simulation. This uses statistical analysis to determine if differences are meaningful or just random variation inherent in Monte Carlo methods.

Diagnostics Toolkit Tutorial

Complete guide to AADC's validation and debugging tools

Overview of the Diagnostics Toolkit

AADC provides a comprehensive suite of diagnostics tools that work together to ensure perfect integration. These tools catch issues early in the development cycle, long before production deployment.

🔧 Toolkit Components

  • Numerical Validator
  • Branch Coverage Analyzer
  • Memory Access Checker
  • Performance Profiler
  • Gradient Validator
  • Kernel Introspection Tools

Complete Diagnostics Workflow

Step 1: Initialize Diagnostics Context

Create an AADC context with full diagnostics enabled. Configure where diagnostic reports should be written and set the desired level of detail in the output (from basic summaries to detailed line-by-line analysis).

Step 2: Configure Validation Rules

Define the acceptance criteria for your integration by setting numerical tolerance levels (both absolute and relative), enabling branch coverage analysis with requirements for completeness, and activating gradient validation with appropriate finite difference parameters for derivative checking.

Step 3: Record with Diagnostics

Begin the recording process with diagnostic tracking enabled. Mark each input variable with descriptive names for easier identification in reports. Execute your pricing function as normal, then mark output variables. The system captures comprehensive diagnostic information throughout the recording process.

Step 4: Run Comprehensive Validation

Execute the recorded kernel with multiple test scenarios covering diverse market conditions: below strike with low volatility, at-the-money with medium volatility, above strike with high volatility, and edge cases with extreme parameter values. The diagnostics system tracks all executions and generates a comprehensive report showing validation results across all scenarios. Reports can be printed to console or exported as HTML for detailed review.

Interpreting Diagnostics Reports

✓ Green Flags (All Good)

  • All numerical differences < tolerance
  • 100% branch coverage achieved
  • Gradients match finite differences
  • No memory access violations
  • Performance within expected range

⚠️ Red Flags (Needs Attention)

  • Numerical differences > 1e-6
  • Incomplete branch coverage detected
  • Gradient mismatches > 1%
  • Memory access errors reported
  • Unexpected performance degradation

Advanced Diagnostics Features

Gradient Validation

AADC can automatically validate AAD-computed gradients against numerically computed finite differences. This provides confidence that the automatic differentiation is working correctly.

Configuration: Enable gradient validation in the context and configure the finite difference method (central, forward, or backward differences) along with the step size for numerical differentiation.

Execution: After recording, execute the kernel with your input values. The system computes both the AAD gradients and corresponding finite difference approximations.

Validation: The validation report compares AAD gradients with finite differences for all inputs. If all gradients match within tolerance, validation succeeds. Otherwise, the report details which gradients have mismatches, their expected vs. actual values, and the magnitude of discrepancies.

Performance Profiling

Profile kernel execution to identify performance bottlenecks and verify expected speedups.

Capabilities: The performance profiler measures total execution time, kernel compilation time, average execution time per call, and identifies computational hotspots within your pricing function.

Analysis: Reports show where computational time is spent, highlighting which operations or function calls consume the most resources. This information helps identify optimization opportunities and verify that vectorization and other optimizations are working as expected.

Use Cases: Validate that kernels achieve expected speedups (6-100x), identify unexpected performance regressions, optimize critical paths in complex pricing models, and ensure efficient resource utilization across large portfolios.

Kernel Introspection

Inspect the properties and characteristics of generated kernels to understand their structure and verify correct generation.

Kernel Statistics: View the total number of operations in the kernel, count of input and output variables, memory footprint required for execution, and vectorization factor (how many values are processed simultaneously with SIMD instructions).

Branch Coverage Information: See the total number of conditional branches in your code, how many branches were covered during recording, and calculate the coverage percentage to ensure all code paths are properly handled.

Applications: Verify that kernels are generated correctly, ensure complete branch coverage before production deployment, understand resource requirements for deployment planning, and validate that expected optimizations (like vectorization) are applied.

Integration Testing Best Practices

📋 Recommended Test Suite

  1. Unit Tests: Test individual functions in isolation with diagnostics enabled
  2. Integration Tests: Test complete pricing workflows with representative scenarios
  3. Regression Tests: Compare AADC results with existing validated results
  4. Edge Case Tests: Test extreme market conditions and boundary values
  5. Stress Tests: Verify performance under high load and large portfolios
  6. Gradient Tests: Validate all derivatives against finite differences

Troubleshooting Common Issues

Issue Likely Cause Solution
Large numerical differences Integration error or incorrect type conversion Check that all relevant variables use idouble; review conversion points
Incomplete branch coverage Insufficient test scenarios during recording Record with more diverse inputs covering all conditional paths
Gradient mismatches Discontinuous function or incorrect marking Verify smooth differentiability; check input/output marking
Performance regression Suboptimal kernel or missing vectorization Review kernel statistics; ensure batch processing is used
Memory access errors Out-of-bounds array access in recorded code Add bounds checking; use diagnostics to identify exact location
Compilation failures Unsupported operation or type mismatch Check AADC compatibility; review error message details

Continuous Integration Setup

Integrating AADC Diagnostics into CI/CD Pipelines

AADC's diagnostics can be seamlessly integrated into your continuous integration and deployment workflows. This ensures that every code change is automatically validated before deployment.

Test Automation: Configure your CI/CD pipeline to run comprehensive AADC tests with full diagnostics enabled, validate numerical accuracy against baseline results, check branch coverage completeness, and verify gradient correctness through automated validation.

Artifact Generation: The pipeline can generate and preserve diagnostic reports (JUnit XML format for test integration, detailed logs for debugging, HTML reports for human review) as build artifacts that can be reviewed by the team.

Quality Gates: Set the validation stage to fail the build if any critical issues are detected, ensuring that problems are caught early in the development cycle before reaching production.

Learn More

Three-phase process: Record computational graph once, JIT compile to optimized machine code, execute thousands of times with 6-1000x speedup.

Technical Findings
  • Near-instantaneous compilation (milliseconds)
  • Automatic vectorization (AVX2/AVX512)
  • Automatic multi-threading
  • Eliminates interpreter overhead

In-depth explanation of the compiler technology and optimization techniques that make MatLogica AADC significantly faster than traditional AAD approaches.

See how our clients transformed their quant libraries

Technical Findings
  • Revolutionary adjoint factor <1 achievement
  • 6-1000x performance improvements
  • Minimal code changes required
  • Production-proven at major banks