You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I checked and did not find my issue in the already reported ones
Describe the bug
With raw denoise enabled on an X-Trans image, the export depends on the number of threads (-t, or the CPU count by default). With the history of integration test 0068, a full-size export with -t 5 differs from one with -t 1 in 6486 pixels, by up to 5/255, in a band across the full width around row 1672. So the same image and history export differently on machines with different CPU counts.
Steps to reproduce
In a darktable checkout with the src/tests/integration submodule, run cd src/tests/integration.
Run compare -metric AE /tmp/t1.png /tmp/t5.png /tmp/diff.png. It prints 6486, and /tmp/diff.png shows a band of changed pixels across the image around row 1672.
Not bisected. The chunked plane extraction came with c61568e (#7202, 2020). Its description says it reduced the differences between thread counts but did not remove them all.
Please provide additional context if applicable. You can attach files too, but might need to rename to .txt or .zip
Other versions: not tried. The runs used master fa3fc72294. The printed version belongs to the build tree, which is one commit later and differs from master only in src/common/darktable.c. The runs linked that file from master.
RAW or JPEG: X-Trans raw only. Bayer raws use another code path.
Fresh edit: the history is the XMP of integration test 0068.
Empty config dir: yes, a new --configdir for every run.
Seen in every run. Repeated -t 5 exports are identical to each other. The integration runner sets OMP_THREAD_LIMIT=4 next to -t 4 so that this test matches its reference (see integration tests for X-Trans demosaic #7087).
Cause (confirmed).wavelet_denoise_xtrans() splits the construction of each color plane into dt_get_num_threads() row chunks (src/iop/rawdenoise.c:338-341). The last row of a chunk copies green values down into the first row of the next chunk (:369). When the chunks run concurrently, that copy lands after the next chunk wrote the row, and the repair block restores a green only if its right neighbor is not green (:429). Where a chunk boundary splits a 2×2 green block, one green in three along the boundary row keeps the value of the green above it. Confirmed two ways. The band disappears when the chunks run one after another (OMP_THREAD_LIMIT=1 with -t 5). Building the plane in a single chunk (nthreads = 1 at :338) makes the -t 4, -t 5 and -t 12 exports identical to -t 1, at a cost of about 0.1 s per 26-megapixel export at 12 threads.
A second defect at the same boundaries leaves one plane position next to the image edge unwritten, see #22457.
Found and reproduced by an AI agent (Claude). Not yet reproduced by a human.
Is there an existing issue for this?
Describe the bug
With raw denoise enabled on an X-Trans image, the export depends on the number of threads (
-t, or the CPU count by default). With the history of integration test 0068, a full-size export with-t 5differs from one with-t 1in 6486 pixels, by up to 5/255, in a band across the full width around row 1672. So the same image and history export differently on machines with different CPU counts.Steps to reproduce
src/tests/integrationsubmodule, runcd src/tests/integration.OMP_NUM_THREADS=1 darktable-cli images/mire1-xtrans.raf 0068-rawdenoise-xtrans/rawdenoise-xtrans.xmp /tmp/t1.png --core --disable-opencl -t 1 --configdir /tmp/dt-t1.OMP_NUM_THREADS=5 darktable-cli images/mire1-xtrans.raf 0068-rawdenoise-xtrans/rawdenoise-xtrans.xmp /tmp/t5.png --core --disable-opencl -t 5 --configdir /tmp/dt-t5.compare -metric AE /tmp/t1.png /tmp/t5.png /tmp/diff.png. It prints6486, and/tmp/diff.pngshows a band of changed pixels across the image around row 1672.Expected behavior
The export is the same for every thread count.
Logfile | Screenshot | Screencast
difference image from step 4:
Commit
Not bisected. The chunked plane extraction came with c61568e (#7202, 2020). Its description says it reduced the differences between thread counts but did not remove them all.
Where did you obtain darktable from?
self compiled
darktable version
5.7.0+1090~gd060937f63-dirty
What OS are you using?
Linux
What is the version of your OS?
Ubuntu 26.04.1 LTS
Describe your system
AMD Ryzen 5 5600X (6 cores, 12 threads), 62 GiB RAM, glibc 2.43, GTK 3.24.52, GraphicsMagick 1.3.46. Only darktable-cli was used.
Are you using OpenCL GPU in darktable?
No
If yes, what is the GPU card and driver?
No response
Please provide additional context if applicable. You can attach files too, but might need to rename to .txt or .zip
fa3fc72294. The printed version belongs to the build tree, which is one commit later and differs from master only insrc/common/darktable.c. The runs linked that file from master.--configdirfor every run.OMP_NUM_THREADSmatches-tbecause on master, darktable-cli crashes on X-Trans images with-tbelow the CPU count (darktable-cli:-t Nbelow the CPU count corrupts the heap #22436, fix in common: restore OpenMP thread limit after GraphicsMagick init #22438).-t 5exports are identical to each other. The integration runner setsOMP_THREAD_LIMIT=4next to-t 4so that this test matches its reference (see integration tests for X-Trans demosaic #7087).Cause (confirmed).
wavelet_denoise_xtrans()splits the construction of each color plane intodt_get_num_threads()row chunks (src/iop/rawdenoise.c:338-341). The last row of a chunk copies green values down into the first row of the next chunk (:369). When the chunks run concurrently, that copy lands after the next chunk wrote the row, and the repair block restores a green only if its right neighbor is not green (:429). Where a chunk boundary splits a 2×2 green block, one green in three along the boundary row keeps the value of the green above it. Confirmed two ways. The band disappears when the chunks run one after another (OMP_THREAD_LIMIT=1with-t 5). Building the plane in a single chunk (nthreads = 1at:338) makes the-t 4,-t 5and-t 12exports identical to-t 1, at a cost of about 0.1 s per 26-megapixel export at 12 threads.A second defect at the same boundaries leaves one plane position next to the image edge unwritten, see #22457.
Found and reproduced by an AI agent (Claude). Not yet reproduced by a human.