Skip to content

feat: add a run-time profile to the standalone driver - #8

Merged
SMI-Lab-Inha merged 5 commits into
devfrom
perf/standalone-profile
Oct 14, 2026
Merged

SMI-Lab-Inha merged 5 commits into
devfrom
perf/standalone-profile

Conversation

@SMI-Lab-Inha

@SMI-Lab-Inha SMI-Lab-Inha commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Summary

Adds an opt-in run-time profile to the standalone driver. This is the measuring tool for the speed work that follows: every later optimisation can report before/after numbers from it, and users can see where a run of their own deck spends its time, with the release executable as well.

With CABLEDYN_PROFILE=1 (the variable the OpenFAST module already reads for its own profile), the driver prints, just before the success line:

  Run-time profile (CABLEDYN_PROFILE), wall-clock time:
    input parsing                             0.002 s    0.0 %
    initialisation and statics                0.233 s    3.1 %
    dynamic march                             7.232 s   96.8 %
      fluid sampled by the driver             0.050 s    0.7 %
      line, cable and object steps            7.168 s   96.0 %
      checks and line failures                0.001 s    0.0 %
      outputs                                 0.013 s    0.2 %
      progress and bookkeeping                0.000 s    0.0 %
    finalisation                              0.000 s    0.0 %
    total                                     7.467 s  100.0 %
    March: 600 committed step(s), 12.0528 ms per step.
    EI = 0 line steps: 3621 (substeps and retries included), Newton iterations: 4661 (1.287 per line step, at most 2).
    Finite-EI cable steps: 4849, residual evaluations: 21255, tangent assemblies: 10391, linear solves: 10391, intervals recovered by substeps: 0.
    Finite-EI cable step time (s): residual 1.416, tangent 2.674, effective matrix 0.136, linear solve 0.943, added mass 0.167, other 0.457.

(examples/buoy_clamped_cable.dat: the 600 march steps cost 4849 cable steps, because the monolithic body step re-steps the clamped cable in every body iteration. That is the kind of lead the profile is for.)

Design

  • New module CableDyn_Profile. It holds process-global phase timers and the phase that is running. CD_Profile_Enter(phase) charges the time since the previous mark to the running phase and starts phase, so the phases add up exactly to the total. The report only flushes the running phase, so a run that stops with an error keeps its time in the phase it stopped in.
  • Where the phases begin.
    • Every time march marks the start of its step, its checks, its output and its progress report. That covers the eight deck-driver routes and the mixed route in the driver program.
    • The existing progress hooks (start_driver_progress, update_driver_progress) start the march and each step's fluid update, or finalisation after the last step.
    • run_deck_driver starts initialisation after the deck input. A static deck enters finalisation after writing its output files.
  • Counters.
    • The EI = 0 line steps and Newton iterations are counted in CD_Step_Model, the one place every tension-only line step passes. The updates are atomic, because lines step inside the system's OpenMP loop.
    • The finite-EI counts are the existing counters of CableDyn_HermiteCableDynamic. They are armed on every route except the mixed EI = 0 + finite-EI route, because these process-global counters would make its aggregate step its cables serially. There the profile states that the cable steps are not counted, so the profiled run executes exactly as an unprofiled one.
    • A march counts a committed step when it has passed its checks, before its outputs.
  • Off by default. Unarmed, each mark is one test of a flag. The library, the C API and OpenFAST are untouched.

Tests

  • New: driver_profile_ei0 (examples/dynamic_chain_waves.dat) and driver_profile_finite_ei (tests/data/held_start_gomex80_power_cable.dat), via tests/check_driver_profile.cmake. Each runs the deck three times: without the variable, with 0, and with 1. It checks that:

    • only the last run prints the profile;
    • every phase row and the route's count line are present;
    • the success line stays the last stdout line;
    • every output file of the three runs is byte-identical.

    I also checked that the script fails as it should: when the expected line is absent, and against a driver built without the feature.

  • New, after review:

    • profile (tests/test_profile.f90) checks the module directly:
      • the phases add up to the elapsed time;
      • a failed run's time stays in the phase it stopped in, and finalisation stays at zero (a mutation that charges the flush to finalisation makes it fail);
      • the line-step counts are exact from a four-thread OpenMP team;
      • nothing is recorded when the profile is not armed.
    • driver_profile_failure checks the printed profile of a run that exits with code 2 (tests/data/nonconvergent_motion.dat).
  • Results unchanged, checked by hand. For eight example decks, one or more per route (single line in waves, multibody, buoy with clamped cable, Hermite cable with vessel motion, spread mooring, static lazy-wave, Rigid6 line break, and the mixed EI = 0 + finite-EI deck run dynamically), every output file is byte-identical with and without the profile. This holds with OMP_NUM_THREADS=1 and with the default threading.

  • Full suite, Windows, gfortran 16.2, OpenBLAS 0.3.33:

    • Release, every test including the slow tier (ctest --test-dir build --output-on-failure): 249/249 pass after the review changes.
    • Debug (-fcheck=all), fast tier (ctest -L fortran -LE slow): 205/205 pass.
  • Documentation: sphinx-build -W is clean and tests/test_documentation.py passes.

  • Overhead (IFX 2025.3.2 release-mirror build, one thread, median of 3): see the table below.

Deck Without the feature Unarmed Armed
chain_two_train_sea 1.87 s 1.88 s 1.89 s
mixed_body_rods_points 3.42 s 3.46 s 3.47 s
lazy_wave_vessel_rao 11.61 s 11.46 s 11.51 s
als_volturnus_line_break_time 38.76 s 39.42 s 39.34 s
buoy_clamped_cable 6.77 s 6.78 s 6.83 s
lozon_gomaine200_power_cable (static) 0.51 s 0.52 s 0.52 s

The differences are within the run-to-run variation of this host. The same unmodified driver measured 37.3 s and 38.8 s on the line-break deck in two sessions.

Checklist

  • pre-commit run --all-files passes
  • ctest --test-dir build --output-on-failure passes
  • python -m pytest tests python/tests passes (if Python or validation records changed) — not applicable, no Python or validation records changed
  • VALIDATION.md updated if a validation result changed — not applicable, no result changes
  • CHANGELOG.md updated under [Unreleased] (heading added if missing) for user-visible changes
  • Documentation in doc/ updated for changed inputs, options, or outputs (doc/cli.rst: Run-time profile; doc/faq.rst; ARCHITECTURE.md)
  • Conventional Commit title (feat:, fix:, docs:, ...)
  • Commits are signed off (git commit -s) under the
    Developer Certificate of Origin

@SMI-Lab-Inha

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T10:13:54.533577Z 5a42c0c Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@read-the-docs-community

read-the-docs-community Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Documentation build overview

📚 CableDyn | 🛠️ Build #35141051 | 📁 Comparing 0fa3575 against latest (f27c5e3)

  🔍 Preview build  

4 files changed
± changelog.html
± cli.html
± development.html
± faq.html

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e287c96a5d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/cabledyn.f90 Outdated
Comment thread src/CableDyn_DeckDriver.f90 Outdated
@SMI-Lab-Inha

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 834e65a7b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/CableDyn_DeckDriver.f90 Outdated
Comment thread app/cabledyn.f90 Outdated
@SMI-Lab-Inha

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4f7bf27624

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/cabledyn.f90 Outdated
Comment thread src/CableDyn_DeckDriver.f90 Outdated
Comment thread src/CableDyn_DeckDriver.f90 Outdated
Comment thread src/CableDyn_DeckDriver.f90 Outdated
@SMI-Lab-Inha

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2070c520f6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/CableDyn_DeckDriver.f90 Outdated
@SMI-Lab-Inha

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 5a42c0cb18

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Speed work on CableDyn needs to know where a run spends its time, on any
build and any deck. Until now the only breakdown was the profile of the
OpenFAST module and the finite-EI step counters, which no standalone run
could switch on.

With CABLEDYN_PROFILE set (the variable the OpenFAST module already
reads), the driver prints, before the success line, the wall time of
input parsing, initialisation and statics, and the dynamic march, split
into the fluid sampled by the driver, the line, cable and object steps,
the checks, the outputs and the progress report, with the time per step.
It also prints the EI = 0 line steps and their Newton iterations, and
the finite-EI cable step counters and times.

The phases are laps taken in the time marches of every route, so they
add up to the total. The EI = 0 counts are taken in CD_Step_Model, the
one place every tension-only line step passes, with atomic updates
because lines step in parallel. Unarmed, each lap is one test of a flag.
The profile only reads the clock: every output file of the eight example
decks tried, one per route, is byte-identical with and without it, with
one OpenMP thread and with the default. Two driver tests check the report
and that identity.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
Review of the run-time profile found two cases where time reached the
wrong phase. Laps charged the time since the previous lap to a phase, so
whatever ran after the last lap fell to finalisation: the parse or
statics of a run that stopped with an error, and the output files that
write_out writes for a static deck.

The profile now tracks the running phase: CD_Profile_Enter charges the
time since the previous mark to it and starts the next one, and the
report only flushes the phase that is running. Each march marks where
its fluid update, step, checks, output and progress report begin; a
run that stops with an error keeps its time in the phase it stopped in
and finalisation stays at zero, and a static deck's output files count
as initialisation.

A unit test checks the partition, a failed run's time kept in its phase
(it fails if a flush charges finalisation instead), and exact line-step
counts from an OpenMP team; a driver test checks the profile of a run
that stops with exit code 2.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
The second review found two phase boundaries that misplaced work. The
deck's wave synthesis or stream-function solve ran before the profile
left the input phase, so it was reported as input parsing; it now
counts as initialisation, while the bathymetry file read stays input.
On the mixed EI = 0 + finite-EI route the step went straight to the
output phase, so its status and convergence checks were charged to the
outputs; it now enters the check phase and moves to the output phase
once the checks pass, as the deck-driver marches do.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
A third review found four more points. The finite-EI step counters are
process-global, so with them armed the aggregate of the mixed EI = 0 +
finite-EI route stepped its cables one after another; the profile now
arms them only on the routes that step their cables in turn anyway, and
on the mixed route reports that the cable steps are not counted, so the
profiled run executes as an unprofiled one. The Hermite and the
objects-only marches entered the output phase before checking the step
status, so a failed step's time went to the outputs; they now check
first. Committed steps were counted in the progress report after the
outputs, so a step whose output failed was missed; every march now
counts a step when it has passed its checks, before its outputs.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
The static route entered the finalisation phase right after write_out,
so a static solve that did not converge, or an output that failed,
charged its error handling to finalisation. It now enters finalisation
only after a converged solve whose output was written.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
@SMI-Lab-Inha
SMI-Lab-Inha force-pushed the perf/standalone-profile branch from 5a42c0c to 0fa3575 Compare October 14, 2026 11:47
@SMI-Lab-Inha
SMI-Lab-Inha merged commit 0213290 into dev Oct 14, 2026
15 checks passed
@SMI-Lab-Inha
SMI-Lab-Inha deleted the perf/standalone-profile branch October 14, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant