Skip to content

Add -j to compile files in parallel - #1235

Open
ru551n wants to merge 7 commits into
VUnit:masterfrom
ru551n:parallel-compile
Open

ru551n wants to merge 7 commits into
VUnit:masterfrom
ru551n:parallel-compile

Conversation

@ru551n

@ru551n ru551n commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Adds -j/--num-compile-threads, the number of files compiled in parallel, independent of -p, so files can be compiled with many threads while tests run with few, for example when the simulator takes a license only to simulate. A file is compiled as soon as the files it depends on are compiled. -j 0 uses all logical CPUs. The default, -j 1, compiles one file at a time as before. --num-sim-threads is added as an alias of -p/--num-threads.

What was added

  • Scheduler: SimulatorInterface.compile_source_files compiles each file once its dependencies are compiled, using a thread pool. As before, the dependents of a failed file are skipped, and --keep-compiling keeps going. Without it, no new files start after a failure.

  • Library rule: GHDL and Riviera-PRO update a library's index without locking it.

    • Two compiles into the same library lose units. Riviera-PRO even reports success for every compile.
    • A compile reading a library while GHDL rewrites its index fails with "cannot find resource library", because GHDL deletes the index before renaming the new one into place.

    Unless a simulator sets supports_concurrent_compiles_into_library, a file is therefore not compiled while its own library is compiled into or read, or while a library it reads is compiled into. The libraries a file reads are those of its dependencies and those named in its library clauses. NVC sets the flag, because it holds a reader/writer lock on its libraries (see NVC performance with Vunit #1036).

  • Library clauses: a library clause fails, in GHDL for example, on a library nothing has been compiled into yet. VUnit now parses library clauses, and a file waits for the first file before it in compile order of each other library it names, so the library exists as it does in a serial compile. A library that comes after the file in compile order fails as it does serially.

  • GHDL: with gcc coverage, GHDL compiles one file at a time, because the .gcno files land in the working directory.

  • Output: with -j > 1, each file's output is written once its compile finishes, so outputs don't mix.

Measured

A clean compile (--compile --clean -j N) of hdl-modules, 330 files, wall time including VUnit's start-up, median of 3 runs:

-j NVC GHDL Riviera-PRO*
master 5.88 s 7.51 s 11.85 s
1 5.95 s 7.51 s 11.90 s
4 2.51 s 5.62 s 7.39 s
16 1.65 s 5.63 s 7.24 s

* With --keep-compiling, because hdl-modules does not compile completely with Riviera-PRO on master either ('latency attribute in sine_calculator.vhd). Every run compiled the same 327 files.

GHDL and Riviera-PRO level off early because almost every file reads vunit_lib, so the library rule serialises most of the compile. The follow-up #1236, built on this PR, addresses that with --batch-compile, which compiles the files of a library that are ready at the same time in one call, the automatic form of the soft file groups discussed in #1088. With both flags, the clean compile of hdl-modules takes 1.42 s with NVC, 1.64 s with GHDL and 2.66 s with Riviera-PRO.

Tested

  • New unit tests for compiling different libraries concurrently, one file per library at a time, the read rule, concurrent readers of a library, waiting for dependencies, skipping dependents and writing each file's output in one piece. They fail on master.
  • UI tests: files are compiled with one thread by default, whatever -p is, and with -j threads otherwise; --num-sim-threads sets -p.
  • The unit and lint tests pass.
  • GHDL stress test: 10 clean hdl-modules compiles each at 4, 16 and 32 compile threads. All 29 runs that reached the compile compiled all 330 files. The 30th failed earlier, on a duplicate configuration name in hdl-modules' own randomised test setup.

A news fragment is included.

🤖 Generated with Claude Code

ru551n and others added 4 commits October 15, 2026 11:25
A file is compiled as soon as the files it depends on are compiled, up to
-p files at a time. Files of a library are compiled one at a time, since
GHDL and Riviera-PRO update the index of a library without locking it and
lose units when compiled into concurrently. NVC locks its libraries and
compiles files of a library at the same time. The output of a file is
written once it is compiled so that outputs do not mix. GHDL compiles one
file at a time with gcc coverage, which writes .gcno files to the working
directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GHDL rewrites the index of a library by deleting it and renaming a new
one into place, so a compile reading the library in between fails with
"cannot find resource library". Unless a simulator locks its libraries, a
file is not compiled while its library is read, or while a library it
reads, that of any of its dependencies, is compiled into.

A library clause fails in GHDL on a library nothing has been compiled
into, which a file compiled in parallel may come before. GHDL creates
every library with ghdl -i when setting up the library mapping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without it, files are compiled one at a time whatever -p is, so that a
-p given for running tests does not change how files are compiled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ru551n ru551n changed the title Compile files in parallel with -p Add --parallel-compile to compile files in parallel Oct 15, 2026
@ru551n
ru551n marked this pull request as ready for review October 15, 2026 12:34
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@LarsAsplund LarsAsplund left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

After fixing this PR, we should continue with the batch compile PR before merging anything. I haven't reviewed that yet and I suspect that there may be some dependencies with this PR that has to be sorted out.

Comment thread docs/news.d/1235.feature.rst Resolved
Comment thread vunit/sim_if/__init__.py Resolved
Comment thread vunit/sim_if/ghdl.py Resolved
Comment thread tests/unit/test_simulator_interface.py Resolved
Comment thread vunit/sim_if/__init__.py Resolved
Comment thread vunit/sim_if/__init__.py Resolved
Replace --parallel-compile with -j/--num-compile-threads, so that
files can be compiled with many threads while tests run with few, and
add --num-sim-threads as an alias of --num-threads. Decide once whether
the output of a file is buffered, type the files compiled as a list and
number the files and libraries of the compile tests from 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ru551n ru551n changed the title Add --parallel-compile to compile files in parallel Add -j to compile files in parallel Nov 6, 2026
@ru551n

ru551n commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

Posted by Claude on behalf of ru551n.

OK, #1236 next. I'll rebase it on these changes, and it will pick up -j instead of --parallel-compile.

Creating an empty GHDL library with ghdl -i is not documented, so it is
removed. Library clauses are parsed instead. A file waits for the first
file before it in compile order of each other library in its library
clauses, so the library exists as it does in a serial compile, and a
library in a library clause counts as read. The database version is
bumped since parse results have changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread docs/cli.rst
while another file is compiled into its library, or into a library it reads. NVC locks its libraries and compiles any
files at the same time. Without ``--parallel-compile``, files are compiled one at a time.
Files are compiled in parallel with ``-j`` (``--num-compile-threads``), independently of the number of tests ``-p``
(``--num-threads`` or ``--num-sim-threads``) runs in parallel. A file is compiled once the files it depends on are

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

runs in parallel -> that runs in parallel

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.

2 participants