Skip to content

fix: add threaded ApplySearch workers - #2373

Merged
colourbill-ctrl merged 1 commit into
masterfrom
ci-qa-pr-thread-connect
Sep 3, 2026
Merged

fix: add threaded ApplySearch workers#2373
colourbill-ctrl merged 1 commit into
masterfrom
ci-qa-pr-thread-connect

Conversation

@xsscx

@xsscx xsscx commented Sep 3, 2026

Copy link
Copy Markdown
Member

PR Summary

#2348

Checklist

  • Signed all Commits in PR
  • Built locally according to docs/build.md
  • Followed the guidelines in Contributing document
  • Ran relevant CTest/profile tests from docs/ctest.md
  • Updated documentation for user-visible behavior changes
  • Ran sanitizer coverage for memory-safety or parser changes
  • Added or updated regression coverage for behavior changes
  • Attached a base...HEAD contract matrix for cross-cutting changes:
    producer, consumer, build/runtime behavior, platform/toolchain boundary,
    CI trigger, dependency owner, and local evidence
  • Reviewed active and suppressed automated findings from review threads and summaries
  • For Python package changes, followed docs/python-packaging-release.md for PR and merge requirements
  • Did not change maintainer-owned workflow, CTest, CPack, sanitizer, release, or security infrastructure unless requested by an iccDEV maintainer
  • New source files include the ICC copyright and BSD 3-Clause license header
  • Code style matches nearby code: 2-space indent, K&R braces, m_ members

Legal Requirements

All official software projects hosted by the International Color Consortium (ICC)
follows the open source software best practice policies. The International Color Consortium IP policy governs ICC specification development and contributions to ICC open source software. Software contributions are also covered by the Contributor License Agreement (CLA).

Contributor License Agreements

Developers who wish to contribute code to be considered for inclusion
in ICC software must first complete a Contributor License Agreement
(CLA)
.

There is no cost or membership requirement to sign the ICC Contributor License Agreement (CLA). Please note that this is different from membership in the International Color Consortium (ICC). If your organization relies on our projects, please become a member. Membership dues are an essential source of funding and investment for these projects.

  • If you are an individual writing the code on your own time and you are SURE you are the sole owner of any intellectual property you contribute, you can sign the CLA as an individual contributor.

  • If you are writing the code as part of your job, or if there is any possibility that your employer might think they own any intellectual property you create, then you should use the Corporate Contributor Licence Agreement

License

ICC software is licensed under the BSD 3-Clause "New" or "Revised" License. Contributions to ICC software projects should abide by that license unless otherwised specified or approved by the ICC.

Copyright Notices

All new source files must begin with the ICC Copyright notice and include or reference the BSD 3-Clause "New" or "Revised" License.

INTELLECTUAL PROPERTY & PATENTS

Participation in ICC's development activities is subject to ICC's Patent Policy.

Maintainer Review Required

If you have questions, contact a listed Maintainer.

@xsscx xsscx added this to the v2.3.2.4 milestone Sep 3, 2026
@xsscx
xsscx requested a balanced review from Copilot September 3, 2026 14:42
@xsscx xsscx self-assigned this Sep 3, 2026
@github-actions github-actions Bot added Documentation Documentation-only or documentation-related change Tools Command-line tool or GUI tool changes Source C or C++ source code changes labels Sep 3, 2026
@xsscx xsscx linked an issue Sep 3, 2026 that may be closed by this pull request
@github-actions github-actions Bot added the pending CI checks still running label Sep 3, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The new threaded ApplySearch behavior lacks focused regression coverage for worker dispatch, output parity, and argument rejection.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds threaded inverse-search processing for iccApplySearch, addressing #2348.

Changes:

  • Adds -threads N CLI support and batched application.
  • Creates independent search apply contexts for worker safety.
  • Extends IccConnect APIs and threading documentation.
File summaries
File Description
Tools/CmdLine/IccApplySearch/iccApplySearch.cpp Adds thread parsing and batch processing.
IccProfLib/IccCmmThread.h Exposes the wrapped base CMM.
IccProfLib/IccCmmSearch.h Adds worker-ready search apply state.
IccProfLib/IccCmmSearch.cpp Implements independent apply contexts.
IccConnect/IccLibConnect/IccConnect.h Declares threaded search factory overload.
IccConnect/IccLibConnect/IccConnect.cpp Wraps search CMMs for threaded execution.
docs/tools-cli-reference.md Documents the CLI option.
docs/icc-connect.md Documents the factory and accessors.
docs/icc-cmm-threading.md Extends threading guidance to ApplySearch.
Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread Tools/CmdLine/IccApplySearch/iccApplySearch.cpp
@xsscx
xsscx requested a balanced review from Copilot September 3, 2026 14:50
@xsscx xsscx added Codex Codex use indicated by Maintainer gpt-daybreak-blue Maintainer indicates use of Codex gpt-daybreak-blue Model labels Sep 3, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The cross-library concurrency, ownership, and public API changes require final human review.

Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@xsscx

xsscx commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

Prior Review from colourbill-ctrl

#2362 (comment)

Review — all 11 Copilot findings resolved at 677657cc; one gap left, and the red leg is not yours

Checked each finding against the tip rather than the commit messages. They read as unresolved
only because no thread has a reply; the code answers all of them.

finding at 677657cc
IccCmmSearch.cpp:427 m_bValid guard leaves m_pApply null fixed — the bAllocNewApply && !m_pApply block allocates on the second call, and checkSearchDeferredApply() covers exactly that sequence
script: 46 reps only reach 3 workers fixed — 49 copies, 4 workers measured below
bare -threads / -threads '' fail open fixed — bare hits the argc < 3 guard; '' hits end == argv[2]
GetSearchCmm() doc contract fixed in icc-connect.md and icc-cmm-threading.md
pErrorMsg empty on attach failure fixed — "failed to attach search CMM"
std::nothrow exception safety fixed — both reserve()s precede every release(), so a throwing reallocation unwinds through the unique_ptrs
CreateSearch bounds check uncovered fixed — iccconnect-threaded-cmm.cpp:50-56 asserts nullptr + the message
3x docs missing the upper bound fixed

Concurrency evidence

The packet the review kept asking for. Clang ThreadSanitizer, -DENABLE_TSAN=ON, Debug;
instrumentation verified (-fsanitize=thread in flags.make, 649 __tsan symbols) rather
than assumed from the cache variable.

Fixture is the script's own: rgb8bit.txt, 49 copies, sRGB_v4_ICC_preference.icc both legs.

run rc TSan warnings output
default 0 0 reference
-threads 1 0 0 byte-identical
-threads 4 0 0 byte-identical

ICC_PERF_STATS_FILE confirms the dispatch is real, not a fallback:

-threads 1   threaded_calls=0  threaded_pixels=0    threaded_active_workers=0
-threads 4   threaded_calls=1  threaded_pixels=784  threaded_active_workers=4

(threaded_worker_strips=3 is activeWorkers - 1 by definition -- three queued, the caller
runs the fourth. Not a shortfall.)

The one gap: the fixture size is unpinned

cmp-ing threaded output against scalar output cannot detect under-dispatch, because
identical output is exactly what the threading is supposed to produce. Measured, same binary:

copies threaded_pixels threaded_active_workers script assertion
1 0 0 passes
46 736 3 passes
49 784 4 passes

Zero threading passes as cleanly as four workers. So the 46 -> 49 bump fixes today's coverage
but nothing holds it there: 49 is coupled to kIccSmallApplyPixelsPerThread = 256, a
file-static in IccCmmThread.cpp -- a different translation unit, with no assertion tying the
two together. Raise that constant, or shrink the fixture, and this test silently stops
exercising threading while staying green.

Two ways to pin it, either fine:

  1. Assert dispatch directly -- set ICC_PERF_STATS_FILE in the script and require
    threaded_active_workers >= 4 for the -threads 4 case. The mechanism is already in tree
    and analysis: add bounded MCS apply profiling #2363 uses it.
  2. Derive the copy count from the constant instead of hardcoding it, so the fixture follows
    the dispatch size automatically.

Same shape as #2150: an anti-vacuity pin has to be relative to what it guards, never an
absolute threshold.

The failing check is infra

Docker Clang 22 Verification fails at step 7, Pull trusted base image, 8s wall. That is the
GHCR base-image pin rotating out, not this branch -- a code failure does not die before the
build starts. Re-run once the pin is refreshed.

Nothing here blocks from my side once the fixture pin is decided.

@xsscx

xsscx commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

Pre Merge Report

2026-09-03 15:04:10 UTC

This PR originates from #2362 which received Maintainer Review as Pasted above. This type of PR should always receive Human Review as Threading & Ownership are the primary issues. This PR followed the Pre-PR Review, Pre-Commit Hook & Pre-Push Security Cycles, clears all implemented Hurdles in ci-pr-action, ci-vcpkg-ports & CI Comprehensive Build and Test.

Final checks in Docker container using ghcr.io/internationalcolorconsortium/iccdev:latest at a412656d8938bac62917173139dce712010529530055258bf78778390e2a2db9

Intent

Merge then continue to next PR which adds the expected CTests & Documentation Updates. Additional updates to include vcpkg SHA update and any workflow or dependency updates needed to avoid workflow failures.

@xsscx

xsscx commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

QA Checks

2026-09-03 15:28:42 UTC

In https://github.com/InternationalColorConsortium/iccDEV/actions/runs/33770806366 this CTest looks too long than expected, but its mid-morning on a Thursday US East. Testing as A/B Test at master:HEAD and PR Branch HEAD.

Research CTest

148/243 Test #148: iccdev.hybrid-pipeline ......................................... Passed 700.09 sec

The Code touches the Testing/hybrid/BuildandTest.sh for Phase 5 & 6. Local Testing indicates the expected Results.

Summary - Its a busy day on CI

@github-actions github-actions Bot added passed All CI checks passed and removed pending CI checks still running labels Sep 3, 2026
@xsscx

xsscx commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

WSL2 Local Build Time Compare

Host

Intel Xeon w5-2465X

master:HEAD build time

Start: 2026-09-03 15:42:01 UTC
Stop: 2026-09-03 15:51:21 UTC

PR Branch Build time

Start: 2026-09-03 15:34:04 UTC
Stop: 2026-09-03 15:42:28 UTC

Repro

git clone https://github.com/InternationalColorConsortium/iccDEV.git
cd iccDEV/Build
git branch && echo "---" && git log --oneline -1
CC=clang CXX=clang++ CXXFLAGS="-fsanitize=address,undefined,integer,bounds,null,float-divide-by-zero,alignment,vla-bound -fno-omit-frame-pointer -g -O0" LDFLAGS="-fsanitize=address,undefined,integer,bounds,null,float-divide-by-zero,alignment,vla-bound" cmake Cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_ASAN=ON -DENABLE_UBSAN=ON -DENABLE_TOOLS=ON -Wl,--build-id
make -j32
        cd ../Testing/
        echo "=== Updating PATH ==="
         for d in ../Build/Tools/*; do
          [ -d "$d" ] && export PATH="$(realpath "$d"):$PATH"
         done
          printf '%s\n%s\n%s\n' 'unsigned-integer-overflow:*/IccMD5.cpp' 'shift-base:*/IccMD5.cpp' 'shift-exponent:*/IccMD5.cpp' > silence.txt && ASAN_OPTIONS='print_scariness=1:halt_on_error=1:detect_leaks=0' UBSAN_OPTIONS='halt_on_error=0:suppressions='"$PWD"'/silence.txt' ./CreateAllProfiles.sh
          printf '%s\n%s\n%s\n' 'unsigned-integer-overflow:*/IccMD5.cpp' 'shift-base:*/IccMD5.cpp' 'shift-exponent:*/IccMD5.cpp' > silence.txt && ASAN_OPTIONS='print_scariness=1:halt_on_error=1:detect_leaks=0' UBSAN_OPTIONS='halt_on_error=0:suppressions='"$PWD"'/silence.txt' ./RunTests.sh
          cd HDR
          printf '%s\n%s\n%s\n' 'unsigned-integer-overflow:*/IccMD5.cpp' 'shift-base:*/IccMD5.cpp' 'shift-exponent:*/IccMD5.cpp' > silence.txt && ASAN_OPTIONS='print_scariness=1:halt_on_error=1:detect_leaks=0' UBSAN_OPTIONS='halt_on_error=0:suppressions='"$PWD"'/silence.txt' ./mkprofiles.sh
          cd ..
          cd Display
          printf '%s\n%s\n%s\n' 'unsigned-integer-overflow:*/IccMD5.cpp' 'shift-base:*/IccMD5.cpp' 'shift-exponent:*/IccMD5.cpp' > silence.txt && ASAN_OPTIONS='print_scariness=1:halt_on_error=1:detect_leaks=0' UBSAN_OPTIONS='halt_on_error=0:suppressions='"$PWD"'/silence.txt' ./RunProtoTests.sh
          cd ..
          cd hybrid
          printf '%s\n%s\n%s\n' 'unsigned-integer-overflow:*/IccMD5.cpp' 'shift-base:*/IccMD5.cpp' 'shift-exponent:*/IccMD5.cpp' > silence.txt && ASAN_OPTIONS='print_scariness=1:halt_on_error=1:detect_leaks=0' UBSAN_OPTIONS='halt_on_error=0:suppressions='"$PWD"'/silence.txt' ./BuildAndTest.sh
          cd ..
          cd CalcTest
          printf '%s\n%s\n%s\n' 'unsigned-integer-overflow:*/IccMD5.cpp' 'shift-base:*/IccMD5.cpp' 'shift-exponent:*/IccMD5.cpp' > silence.txt && ASAN_OPTIONS='print_scariness=1:halt_on_error=1:detect_leaks=0' UBSAN_OPTIONS='halt_on_error=0:suppressions='"$PWD"'/silence.txt' ./checkInvalidProfiles.sh
          cd ..
          cd mcs
          printf '%s\n%s\n%s\n' 'unsigned-integer-overflow:*/IccMD5.cpp' 'shift-base:*/IccMD5.cpp' 'shift-exponent:*/IccMD5.cpp' > silence.txt && ASAN_OPTIONS='print_scariness=1:halt_on_error=1:detect_leaks=0' UBSAN_OPTIONS='halt_on_error=0:suppressions='"$PWD"'/silence.txt' ./updateprev.sh
          printf '%s\n%s\n%s\n' 'unsigned-integer-overflow:*/IccMD5.cpp' 'shift-base:*/IccMD5.cpp' 'shift-exponent:*/IccMD5.cpp' > silence.txt && ASAN_OPTIONS='print_scariness=1:halt_on_error=1:detect_leaks=0' UBSAN_OPTIONS='halt_on_error=0:suppressions='"$PWD"'/silence.txt' ./updateprevWithBkgd.sh
          cd ..

@xsscx

xsscx commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

Codex Report

Local iccApplySearch Threading and ISA QA

2026-09-03 16:44:54 UTC
Edited by @xsscx

Tested PR HEAD 971f4cf64bac438e061dcab74a9f0c002bf99134 on WSL2 with an Intel Xeon w5-2465X and CPU affinity fixed to 0-15.

Direct iccApplySearch threading benchmark

The tracked It8Cmyk.txt fixture contains 1,617 color-data rows. This exceeds the 1,024-pixel bulk threshold and activates every requested worker for the 1-, 2-, 4-, and 8-thread cases. Seven interleaved repetitions were run per thread count using the GCC Release ASan/UBSan build.

Threads Median elapsed Range Speedup vs 1 thread
1 3.30 s 3.10-3.40 s 1.00x
2 2.20 s 2.10-2.20 s 1.50x
4 1.50 s 1.40-1.50 s 2.20x
8 1.10 s 1.10-1.10 s 3.00x

All 28 executions passed and produced byte-identical output:

39ae384f7084d1aa81a212c08646c27b6cce6c83215d3336b09d97f679f47443

No stderr or sanitizer diagnostics were emitted.

Portable, AVX2, and AVX-512 coverage

Independent Clang Release builds ran iccdev.clut-eight-output-regression five times each:

Variant Result Median end-to-end time
Portable 5/5 passed 0.12 s
AVX2 5/5 passed 0.11 s
AVX-512 5/5 passed 0.12 s

The separate iccdev.clut-avx512-sixteen-output parity test also passed. These short CLUT measurements establish cross-ISA correctness coverage; they are not evidence that one ISA is faster than another.

Finding

The direct workload confirms useful iccApplySearch scaling through eight active workers, reaching 3.00x lower elapsed time at eight threads with identical output. No functional, sanitizer, or ISA-specific regression was observed. Results are local and workload-specific.

@xsscx xsscx assigned colourbill-ctrl and unassigned xsscx Sep 3, 2026
@xsscx xsscx mentioned this pull request Sep 3, 2026
13 tasks

@colourbill-ctrl colourbill-ctrl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed at 971f4cf6. Threading and ownership hold: each worker owns private apply objects per sub-CMM, the sub-CMMs are read-only after Begin(), and the GetSearchCmm() unwrap is load-bearing -- iccApplySearch.cpp:472 would dereference null without it. Built clean on gcc, TSan and ASan+LSan; master's five existing CTests pass against it, four TSan-clean; output byte-identical at 1/4/8/auto across five input shapes including -cfg; 8.8s -> 2.0s at auto on 14 cores. 3df113ca was the right call -- clearing m_bValid would send a retry back through a body that is not re-runnable.

Approving. The #2362 test files apply clean on this head if you want them as PR 2; PR-2 notes (a threshold line in the CLI docs, a size assert in the batch path) go in a follow-up issue rather than here.

@colourbill-ctrl
colourbill-ctrl merged commit 3e2224d into master Sep 3, 2026
48 checks passed
@xsscx

xsscx commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

Post Merge Report

2026-09-03 19:17:34 UTC

  1. Nothing to Report
  2. Helgrind hit the atoi() in ApplyProfiles

Opening an Issue now...

@xsscx
xsscx deleted the ci-qa-pr-thread-connect branch September 4, 2026 14:55
xsscx added a commit that referenced this pull request Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Codex Codex use indicated by Maintainer Documentation Documentation-only or documentation-related change gpt-daybreak-blue Maintainer indicates use of Codex gpt-daybreak-blue Model passed All CI checks passed Source C or C++ source code changes Tools Command-line tool or GUI tool changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI: Perf: Add Threading to iccApplySearch

3 participants