Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ layout: learningpathall

QuantLib is an open-source C++ library for quantitative finance. It provides tools for pricing, modeling, trading, and risk management, and is widely used as both a development library and a representative financial computing workload.

Because QuantLib is a substantial C++ codebase with realistic compute behavior, it is also useful as a benchmark when evaluating cloud systems and processor architectures. In this Learning Path, you will build QuantLib from source and run its benchmark executable on an Arm-based Azure Cobalt virtual machine.
Because QuantLib is a substantial C++ codebase with realistic compute behavior, it's also useful as a benchmark when evaluating cloud systems and processor architectures. In this Learning Path, you'll build QuantLib from source and run its benchmark executable on an Arm-based Azure Cobalt virtual machine.

## Why use Azure Cobalt?

Azure Cobalt provides Arm64 virtual machines for cloud-native development and performance evaluation. Running QuantLib on Azure Cobalt gives you a practical way to measure how a real C++ finance workload behaves on Arm-based cloud infrastructure.

The workflow uses:
You'll use:

- Ubuntu Server 22.04 LTS (also tested on 24.04 LTS)
- an Arm64 Azure Cobalt virtual machine
- a source build of QuantLib
- Ubuntu Server 22.04 LTS
- An Arm64 Azure Cobalt virtual machine
- A source build of QuantLib
- QuantLib's benchmark executable for repeatable performance testing

## Benchmark workflow
Expand All @@ -34,32 +34,38 @@ The steps follow a practical benchmark flow:
5. Compare and record results

{{% notice Note %}}
This Learning Path focuses on building and benchmarking QuantLib on Azure Cobalt. It is not a general introduction to quantitative finance or QuantLib development.
The steps in this Learning Path aren't a general introduction to quantitative finance or QuantLib development.
{{% /notice %}}

## What the benchmark tests

The benchmark executable runs approximately 85 tests drawn directly from QuantLib's own test suite, covering five domains:

- **Equity and FX**: American and European option pricing, Heston and Bates model calibration, convertible bonds, Andreasen-Huge volatility interpolation
- **Interest rates**: Short rate models, Bermudan swaptions, Libor market model, piecewise yield curves, overnight indexed swaps, Markov functional models, SABR and ZABR volatility
- **Credit derivatives**: Nth-to-default pricing and credit default swap calibration
- **Energy**: Swing options and virtual power plant pricing
- **Math**: Gaussian quadratures, low-discrepancy sequences, statistics, and special functions
- Equity and FX: American and European option pricing, Heston and Bates model calibration, convertible bonds, Andreasen-Huge volatility interpolation
- Interest rates: Short rate models, Bermudan swaptions, Libor market model, piecewise yield curves, overnight indexed swaps, Markov functional models, SABR and ZABR volatility
- Credit derivatives: Nth-to-default pricing and credit default swap calibration
- Energy: Swing options and virtual power plant pricing
- Math: Gaussian quadratures, low-discrepancy sequences, statistics, and special functions

Each test has a fixed iteration count built in. Some run once per task, others run hundreds or thousands of times to produce a measurable signal. The `--size` argument multiplies the entire set: `--size=2` runs each test twice, `--size=5` runs it five times, and so on. Doubling `--size` doubles runtime while leaving throughput unchanged — this is the expected weak scaling behavior of the benchmark.
Each test has a fixed iteration count built in. Some run once per task, and others run hundreds or thousands of times to produce a measurable signal. The `--size` argument multiplies the entire set: `--size=2` runs each test twice, `--size=5` runs it five times, and so on. Doubling `--size` doubles runtime while leaving throughput unchanged — this is the expected weak scaling behavior of the benchmark.

The `--nProc` argument controls the number of worker processes. Because QuantLib is not thread-safe, the benchmark uses separate processes rather than threads, coordinated through Boost IPC. Before timing begins, the benchmark runs every test once through the Boost unit test framework to verify correctness — this is what produces the `*** No errors detected` line in the output.
The `--nProc` argument controls the number of worker processes. Because QuantLib is not thread-safe, the benchmark uses separate processes rather than threads, coordinated through Boost IPC. Before timing begins, the benchmark runs every test once through the Boost unit test framework to verify correctness. The tests produce the `*** No errors detected` line in the output.

**System Throughput** is calculated as `(size × number_of_tests) / total_runtime`. It is the primary metric for comparing runs across thread counts and system configurations.
`System Throughput` is calculated as `(size × number_of_tests) / total_runtime` and is the primary metric for comparing runs across thread counts and system configurations.

## Benchmarking goals

When benchmarking a workload such as QuantLib, the goal is not just to obtain one runtime number. You want a repeatable process that lets you compare runs across system sizes, thread counts, software versions, and compiler settings.

For that reason, this Learning Path emphasizes:

- using a known VM configuration
- keeping the software environment consistent
- changing one benchmark variable at a time
- recording commands and results so runs can be reproduced later
- Using a known VM configuration
- Keeping the software environment consistent
- Changing one benchmark variable at a time
- Recording commands and results so runs can be reproduced later

## What you've learned and what's next

You've now learned about QuantLib and why you'll be using Azure Cobalt in this Learning Path. You've also learned how the benchmark works and the intent behind benchmarking a workload such as QuantLib.

Next, you'll set up your Azure Cobalt environment.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ layout: learningpathall

## Create and connect to an Arm64 Azure Cobalt virtual machine

To run QuantLib on Azure Cobalt, first create an Arm64 Ubuntu virtual machine in the Azure portal.
To run QuantLib on Azure Cobalt, first create an Arm64 Ubuntu virtual machine (VM) in the Azure portal. For detailed steps, see the Azure documentation [Quickstart: Create a Linux virtual machine in the Azure portal](https://learn.microsoft.com/en-us/azure/virtual-machines/linux/quick-create-portal?tabs=ubuntu).

Use the following settings:

| Setting | Value |
|---|---|
| Virtual machine name | `quantlib-cobalt-vm` |
| Region | a Cobalt-supported region such as **West US 2** |
| Region | A Cobalt-supported region such as **West US 2** |
| Availability options | No infrastructure redundancy required |
| Security type | Standard |
| Image | Ubuntu Server 22.04 LTS |
Expand All @@ -25,13 +25,13 @@ Use the following settings:
| SSH public key name | `quantlib-cobalt-vm_key` |
| Username | `azureuser` |

For storage, a `64 GB` OS disk is sufficient for this workflow.
A `64 GB` OS disk is sufficient storage for this workflow.

For networking, allow inbound SSH on port `22`. Restricting the source to **My IP** is recommended.

After creating the VM, download the generated private key in `.pem` format if Azure provides one during setup.

Before connecting, update the permissions on the private key from your local machine. SSH refuses to use keys that are readable by other users:
SSH refuses to use keys that are readable by other users. Before connecting to the VM, update the permissions on the private key from your local machine:

```bash
chmod 600 ~/Downloads/quantlib-cobalt-vm_key.pem
Expand All @@ -46,19 +46,19 @@ ssh -i ~/Downloads/quantlib-cobalt-vm_key.pem azureuser@<VM_PUBLIC_IP>
Replace `<VM_PUBLIC_IP>` with the public IP address of your VM.


After logging in, verify the architecture before installing packages. The rest of this Learning Path assumes you are on an Arm64 system:
After logging in, verify the architecture before installing packages. The rest of this Learning Path is intended to be run on an Arm64 system:

```bash
uname -m
```

The expected output is:

```bash
```output
aarch64
```

If you do not see aarch64, check that you created the VM with Arm64 architecture and selected an Azure Cobalt-compatible instance type.
If you don't see `aarch64`, check that you created the VM with Arm64 architecture and selected an Azure Cobalt-compatible instance type.

## Install dependencies and download QuantLib

Expand Down Expand Up @@ -86,9 +86,9 @@ Check that the file exists and has a non-zero size:
ls -lh QuantLib-$QL_VER.tar.gz
```

You should see output showing the file name and size, for example:
The output shows the file name and size, and is similar to:

```bash
```output
-rw-r--r-- 1 azureuser azureuser 41M QuantLib-1.41.tar.gz
```

Expand All @@ -102,42 +102,39 @@ Use the `file` command to confirm that the archive is a gzip-compressed tar file
file QuantLib-$QL_VER.tar.gz
```

Expected output is similar to:
The output is similar to:

```bash
```output
QuantLib-1.41.tar.gz: gzip compressed data, max compression, from Unix, original size modulo 2^32 42721280
```

Once confirmed, extract it and move into the extracted directory:
After you've confirmed, extract the archive and move into the extracted directory:

```bash
tar -xzf QuantLib-$QL_VER.tar.gz
cd QuantLib-$QL_VER
```



List the contents to confirm that the source code is ready to configure and build:

```bash
ls
```

You should see files and directories such as:
The output is similar to:

```bash
```output
configure
Makefile.am
ql/
test-suite/
```

This confirms that the source code has been unpacked correctly and is ready to configure and build.
The output confirms that the source code has been unpacked correctly and is ready to configure and build.

{{% notice Optional Setup %}}
## Reconnect to Cobalt frequently
## (Optional) Set up shortcut for reconnecting to Cobalt frequently

If you'll reconnect often, add a shortcut entry to your SSH config:
If you'll reconnect to the VM often, add a shortcut entry to your SSH config:

```bash
nano ~/.ssh/config
Expand All @@ -158,7 +155,7 @@ Then connect with:
ssh quantlib-cobalt
```

## Use tmux for remote builds
## (Optional) Use tmux for remote builds

If your SSH session disconnects during the build, the compile job will be killed. To prevent this, install tmux and start a session before running `make`:

Expand All @@ -168,11 +165,14 @@ sudo apt install -y tmux
tmux
```

Run the build commands from inside the tmux session. If your connection drops, reconnect to the VM and re-attach with:
Run the build commands from inside the tmux session. If your connection drops, reconnect to the VM and re-attach:

```bash
tmux attach
```
{{% /notice %}}

With your environment set up, move on to the next section to build QuantLib.
## What you've accomplished and what's next

You've now set up an Azure Cobalt virtual machine to run QuantLib on. You've also installed QuantLib dependencies and then downloaded QuantLib.

Next, with your environment set up, you'll build QuantLib.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ layout: learningpathall

## Configure the build

Return to the QuantLib source directory. This uses the `QL_VER` variable you exported when downloading the source archive:
Return to the QuantLib source directory. The command uses the `QL_VER` variable that you exported when downloading the source archive:

```bash
cd ~/QuantLib-$QL_VER
Expand All @@ -24,13 +24,7 @@ CFLAGS="-g -O2 -mcpu=native" \
CXXFLAGS="-g -O2 -mcpu=native"
```

This configuration:

- installs QuantLib to `/usr/local`
- enables the benchmark executable
- enables parallel test execution
- applies CPU-specific optimization flags

This configuration installs QuantLib to `/usr/local`. It enables the benchmark executable and parallel test execution, and it applies CPU-specific optimization flags.

## Install QuantLib

Expand All @@ -41,7 +35,7 @@ make -j$(nproc)
```

{{% notice Note %}}
The build may take 30–45 minutes on the Standard_D4ps_v5. If your SSH session might disconnect, set up tmux before running `make` — see the optional setup steps in the previous section.
The build may take 30–45 minutes on the Standard_D4ps_v5. If your SSH session might disconnect, set up tmux before running `make` — see [(Optional) Use tmux for remote builds](/learning-paths/servers-and-cloud-computing/quantlib/2-setup-environment/#optional-use-tmux-for-remote-builds) in the previous section.
{{% /notice %}}

After the build completes, install QuantLib into `/usr/local` and refresh the dynamic linker cache:
Expand All @@ -58,4 +52,10 @@ cd ~/QuantLib-$QL_VER/test-suite
ls quantlib-benchmark
```

You should see `quantlib-benchmark` in the output. You will use this executable in the next section.
You should see `quantlib-benchmark` in the output. You'll use this executable in the next section.

## What you've accomplished and what's next

You've now completed the installation of QuantLib after building it with support for benchmarking.

Next, you'll run benchmarks on QuantLib with different sizes and thread counts.
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ layout: learningpathall
---
## Run a baseline benchmark

After building QuantLib, move to the test suite directory and run the benchmark with its default settings:
After building QuantLib, move to the test suite directory and run the benchmark with its default settings. The command uses the `QL_VER` variable that you exported when downloading the source archive:

```bash
cd ~/QuantLib-$QL_VER/test-suite
./quantlib-benchmark
```

This confirms that the benchmark is working correctly on your system.
Successfully running the benchmark with default settings confirms that the benchmark is working correctly on your system.

To understand how performance scales across the Arm cores in the VM, keep the workload size constant and change only the number of worker processes:

Expand All @@ -24,23 +24,23 @@ To understand how performance scales across the Arm cores in the VM, keep the wo
./quantlib-benchmark --size=80 --nProc=4
```

The Standard_D4ps_v5 virtual machine has a limited number of cores. Start with 1, 2, and 4 workers. Larger values such as 12, 24, or 48 are better suited to larger machines and can oversubscribe this VM, which makes the results harder to interpret.
The `Standard_D4ps_v5` virtual machine has a limited number of cores. Start with 1, 2, and 4 workers. Larger values such as 12, 24, or 48 are better suited to larger machines and can oversubscribe this VM, which makes the results harder to interpret.

## Vary workload size

Next, keep the thread count fixed and vary the problem size. This shows how runtime changes as the benchmark does more work:
Next, keep the thread count fixed and vary the problem size. By using varied problem sizes, you can see how runtime changes as the benchmark does more work:

```bash
./quantlib-benchmark --size=1 --nProc=1
./quantlib-benchmark --size=5 --nProc=1
./quantlib-benchmark --size=8 --nProc=1
```

## Interpreting the output
## Interpret the output

The `--size=1 --nProc=1` run is the quickest of the three, completing in roughly 2 minutes 25 seconds on this configuration. It's a good first check before committing to longer runs. Adding `--verbose=2` prints a per-test runtime breakdown alongside the summary. Without it, only the summary block is printed. Verbosity levels run from 0 (summary only) to 2 (per-test detail); level 3 adds internal debug output.
The `--size=1 --nProc=1` run is the quickest of the three, completing in roughly 2 minutes 25 seconds on this configuration. It's a good first check before committing to longer runs. Adding `--verbose=2` prints a per-test runtime breakdown alongside the summary. Without it, only the summary block is printed. Verbosity levels run from 0 (summary only) to 2 (per-test detail). Level 3 adds internal debug output.

The first run with `--size=1 --nProc=1 --verbose=2` produces output similar to the following. The benchmark first confirms that all tests passed, then lists the runtime for each individual test, and finishes with a summary:
The first run with `--size=1 --nProc=1 --verbose=2` produces output similar to the following:

```output
*** No errors detected
Expand All @@ -64,14 +64,22 @@ Num. Worker Processes = 1
Tail Effect Ratio = 1
```

The **System Throughput** and **Benchmark Runtime** values are what you'll compare across runs. The individual test lines show which computations dominate total runtime — longer-running tests such as `testMultiStepCmSwapsAndSwaptions` and `testGauss` reflect the most numerically intensive parts of the workload.
The benchmark first confirms that all tests passed, then lists the runtime for each individual test, and finishes with a summary.

The `System Throughput` and `Benchmark Runtime` values are what you'll compare across runs. The individual test lines show which computations dominate total runtime. Longer-running tests such as `testMultiStepCmSwapsAndSwaptions` and `testGauss` reflect the most numerically intensive parts of the workload.

## Keep benchmark runs controlled

For meaningful comparisons:

* change one parameter at a time
* keep the environment consistent
* repeat runs if results vary
- Change one parameter at a time
- Keep the environment consistent
- Repeat runs if results vary

Doing so ensures that differences in runtime reflect real performance changes.

## What you've accomplished and what's next

You've now benchmarked QuantLib with default settings and with varied workloads. You've also reviewed the output of the benchmark.

This helps ensure that differences in runtime reflect real performance changes.
Next, you'll further analyze and compare benchmark results.
Loading
Loading