Sinds ik Darktable begon te gebruiken, rond 2012, was ik altijd verbaasd over hoe weinig RAM het gebruikte. Mensen denken dat het goed is dat een applicatie zuinig omgaat met het geheugen, en dat is zeker waar als we het over je desktopomgeving hebben. Maar als we het hebben over productiesoftware die zware pixelberekeningen uitvoert op afbeeldingen van 12 tot 54 Mpixels, dan betekent dit dat dezelfde zware berekeningen keer op keer worden uitgevoerd in plaats van te worden bewaard om later hergebruikt te worden. Daar dient een cache voor: het vermijden van dure berekeningen. En hij zou daarvoor alle beschikbare RAM moeten gebruiken, want rekenen is energie verspillen, en dat heeft een concrete impact als je op batterij werkt. Bovendien heb je voor die RAM betaald en het gebruiken ervan maakt je batterij niet leeg. De CPU/GPU daarentegen…

Ja, fotoreporters en veel digitale nomaden retoucheren op batterijgevoede laptops, ter plaatse. Het wordt tijd dat de opensourcewereld beseft dat niet alle fotografen ’s avonds en in het weekend aan hun bureau zitten, na hun „echte" dagbaan. Dus dezelfde dingen keer op keer opnieuw berekenen is simpelweg energie verspillen, of je nu in het stopcontact zit of op batterij werkt.

Ondertussen had Darktable altijd die vreemde kleine RAM-instelling waarmee je kon bepalen hoeveel je wilde dat het gebruikte. Alleen had het geen enkele manier om daadwerkelijk bij te houden hoeveel RAM het gebruikte, dus was het meer een richtlijn dan een regel. Dat werd later vervangen door een volkomen idiote kwalitatieve „resources"-voorkeur die zowel niets betekent als je feitelijk niet vertelt hoeveel RAM je aan de software toewijst.

Dus de RAM-cache van Darktable heeft nooit echt gewerkt, werd onderbenut en moest gerepareerd worden. Want als gevolg daarvan werd alles de hele tijd opnieuw berekend zonder enige reden.

Maar… Er was een reden waarom de cache onderbenut werd en niet echt werkte: die software had geen enkel zicht op de levenscyclus van de gegevens, wat zo’n beetje de voorwaarde is als je gegevens wilt opslaan om te hergebruiken. Dat kwam voort uit een pixelpipeline die echt ingewikkeld was (ik vraag me oprecht af of er onder de Darktable-„developers" iemand in staat is om het stroomschema te tekenen van wat we met pixels doen, van begin tot eind), maar ook uit afbeeldingsmetadata die op verschillende plaatsen werden berekend, gekopieerd en opgeslagen (en vervolgens gedeeltelijk bijgewerkt) op verschillende plaatsen…

De pipelinecache had één doel: het toewijzen van de invoer- en uitvoerbuffers van modules, en deze eventueel hergebruiken als ze al beschikbaar waren. Maar zijn grootte werd gedefinieerd in aantal items, wat echt beperkt was, en niet in de hoeveelheid toegewezen geheugen. Dat maakte hem matig nuttig en dwong ons hem veel te behoudend te gebruiken, omdat zijn werkelijke geheugengrootte volledig onvoorspelbaar was.

Onnodig te zeggen dat „het repareren van de cache" impliceerde „het repareren van de pipeline", wat op zijn beurt impliceerde „de levenscyclus van de gegevens zichtbaar, traceerbaar en globaal beheerd maken", wat impliceerde de architectuur op hoog niveau van de software te herontwerpen. Zoals we zullen zien, had dit onverwachte voordelen voor de prestaties, die de module-gewijze interne optimalisaties die Darktable in dezelfde tijd deed ruimschoots overtreffen.

Wat er sinds 2022 veranderd is

Dit artikel is het directe vervolg op De pipelinecache en 10 jaar oude bugs repareren. Dat vorige hoofdstuk ging over het vinden van de rot en het stoppen van de meest gênante mislukkingen. Dit gaat over wat er daarna gebeurde, toen het duidelijk werd dat de cachebugs helemaal geen geïsoleerde bugs waren, maar symptomen van een renderer waarvan de verantwoordelijkheden veel te lang door elkaar waren gehaald.

Waar dit historisch inpast

Het oorspronkelijke probleem was niet louter „de cache cachet niet genoeg". Het werkelijke probleem was dat de hele pipelinestack rondom toevallig gedrag was gegroeid. GUI-herteningen konden uiteindelijk beeldverwerking starten, op een ongereguleerde manier. Maskervoorbeelden lekten GUI-status in de renderer. De logica van histogram en kleurenpipet was afhankelijk van speciale bijeffecten van de pipeline. Export, miniaturen, voorbeeld en donkere kamer hadden allemaal hun eigen kleine variaties van „vast kunnen we die buffer nog één keer kopiëren". En telkens wanneer consistentie moeilijk te bewijzen werd (tijdens maskerweergave of uitsnedewijzigingen), was de terugvalstrategie vaak om cacheregels te legen en alles opnieuw te berekenen, want blijkbaar telde „steek het in brand en begin opnieuw" een tijdlang als architectuur.

Sommige codeopmerkingen zeiden dit al. Er waren waarschuwingen over herbeekening aangedreven door hertening. Er was zelfs een oude notitie die zei dat de cache uiteindelijk globaal zou moeten worden. Dus de laatste paar jaar gingen niet over het uitvinden van een nieuwe theorie vanaf nul. Ze gingen vooral over het eindelijk uitvoeren van de opruiming waar de code al sinds de jaren 2010 om smeekte.

De belangrijkste historische verschuiving is dat de pipeline niet langer werd behandeld als één recursieve klont waarvan verwacht werd dat hij tijdens het draaien zijn eigen behoeften ontdekte. Hij werd geleidelijk opgesplitst in duidelijkere uitvoeringspaden voor interactieve rendering, headless rendering, GPU-verwerking, CPU-verwerking en GUI-zijdige consumenten. Tegelijkertijd werd GUI-gedrag terug naar de GUI geduwd. Tekenen werd weer tekenen. Verwerken werd weer verwerken. Dat klinkt banaal, wat meestal een teken is dat het vorige ontwerp absurd was geworden.

Checksums, of hoe geldigheid ophield een gokspel te zijn

Zodra de renderer niet langer verstrengeld was met elke widget en elk zijkanaal, werd het mogelijk om de beeldstatus expliciet te definiëren. Elk historie-item draagt nu een modulechecksum die is opgebouwd uit moduleparameters, mengparameters en eventuele relevante maskervormen. Dat geeft elke modulestatus een canonieke vingerafdruk zodra hij in de historie terechtkomt, in plaats van de geldigheid later te laten afleiden uit wat er toevallig gedraaid heeft.

Dat alleen was niet genoeg, want een pipeline is niet zomaar een stapel module-instellingen. Hij hangt ook af van volgorde, region of interest, buffercontracten en weergavegerelateerde status. Dus de planningsfase verzamelt die vingerafdrukken op moduleniveau door de hele keten heen en vouwt de rest van het runtimecontract erin voordat er ook maar één pixel beweegt. Het resultaat is een stabiele identiteit per fase en een uiteindelijke pipeline-identiteit.

Dit is waar de zichtbaarheid eindelijk verschijnt. De pipeline kan weten of hij nog geldig is door zijn historie-hash te vergelijken. De weergegeven backbuffer kan weten of hij nog overeenkomt met de huidige pipe- en historiestatus. Een cacheregel kan weten of hij echt bij precies de fase, ROI en parameters hoort die op dat moment worden opgevraagd. Dat klinkt bijna beledigend redelijk, maar het vereiste eerst veel opruiming: de synchronisatie van de historie met de pipeline moest expliciet gemaakt worden, cache-bypass moest vooraf gedeclareerd worden (voor maskervoorbeeld en uitsnedebewerkingen), maskerweergave mocht de regels niet langer halverwege de uitvoering muteren, en de oude door hertening geactiveerde bijeffecten moesten weg. Je krijgt geen betrouwbare hashes bovenop onbetrouwbare besturingsstroom.

Het praktische voordeel is dat consistentie niet langer door bijgeloof wordt gehandhaafd. We hoeven niet meer te vragen „heeft de GUI waarschijnlijk het juiste ding op het juiste moment ongeldig gemaakt?" Het antwoord staat in de checksums. Ofwel komt de status overeen, ofwel niet. En we kunnen elke module-uitvoer vanuit de GUI-laag pakken, zonder een pipeline te draaien, omdat de modulechecksum voorspelbaar is en vooraf of parallel aan de rendering kan worden berekend.

De cache-first-architectuur

Betrouwbare hashes veranderen de architectuur bijna vanzelf. Zodra elke betekenisvolle pipelinestatus een stabiele identiteit heeft die vooraf bekend is, houdt de cache op een best-effort-optimalisatie te zijn en wordt hij het centrum van de dataflow.

Daarom heeft de pipeline nu een echte planningsfase vóór de uitvoering. Eerst wordt de historie gesynchroniseerd. Regions of interest worden door de volledige keten gepropageerd. Elke fase krijgt een expliciet invoer- en uitvoercontract. Het cachebeleid aan de hostzijde wordt verzegeld vóór runtime. Globale hashes worden berekend vóór de uitvoering. Met andere woorden, de engine weet wat hij gaat doen voordat hij begint met doen, wat een verfrissende breuk is met de oudere methode van er halverwege achter komen en compenseren met hacks.

Vanaf daar worden cache-opzoekingen deterministisch. Een fase kan precies de buffer heropenen die bij zijn status past, zodat een module berekeningen volledig kan omzeilen door louter in de cache te kijken of er al een cacheregel overeenkomt met zijn interne status als een checksum-opzoeking. Consumenten verderop kunnen gepubliceerde resultaten heropenen op hash in plaats van de renderer te vragen nog één speciale dans voor hen uit te voeren. De cache houdt op een stapel vaag herbruikbaar geheugen te zijn en wordt het gezaghebbende register van geldige tussentijdse en uiteindelijke resultaten.

Dit verklaart ook waarom er zoveel code verwijderd of vereenvoudigd kon worden. Zodra geldigheid gecentraliseerd is, heb je minder heuristieken nodig, minder speciale vertakkingen, minder „behalve wanneer de GUI in deze modus staat"-clausules, en minder noodlegingen. De code wordt korter, niet omdat het probleem kleiner werd, maar omdat het niet langer op zes tegenstrijdige plaatsen tegelijk werd opgelost.

Cacheregels binden ook GPU- en CPU-geheugen, wat ons in staat stelt om OpenCL pinned memory te gebruiken. Er is al sinds mensenheugenis een OpenCL-gebruikersvoorkeur die het mogelijk maakte om pinned memory in of uit te schakelen, maar ik ontdekte dat die optie alleen werd gebruikt voor verwerking in tegels, wanneer modules hun volledige geheugenbehoefte niet op de GPU pasten. Pinned memory is nu ook uitgebreid naar normale bewerkingen, aangezien het RAM en VRAM in staat stelt om zonder kopiëren te worden gemapt. Het gebruik van pinned memory op een volledig gecachte GPU-pipeline verlaagt de tijd besteed aan het verplaatsen van geheugenbuffers met een factor tot 7.

Maar het geforceerd cachen van OpenCL-module-uitvoer, zelfs met zero-copy pinned buffers, heeft nog steeds enige kosten, en is duurder dan de cache gewoon volledig overslaan. Voor sommige zware modules (denoise profiled, diffuse or sharpen, contrast equalizer) is de cache-overhead de moeite absoluut waard, maar voor snelle modules (white balance, exposure, input color profile) maakten de kosten van het cachen van OpenCL-buffers dat de hele modules op de GPU feitelijk langzamer draaiden dan op de CPU.

Dus we hebben nu per-module-heuristieken die beslissen of een OpenCL-module zijn uitvoerbuffer op de RAM-cache zal publiceren. Zware modules en alle modules die kleurenpipet of histogrammen vastleggen worden standaard gepubliceerd. Voor de overige kunnen gebruikers zelf beslissen:

image

Dit zal gebruikers ook in staat stellen om OpenCL selectief uit te schakelen op sommige modules wanneer ze er terugkerende problemen mee hebben. Bijvoorbeeld, denoise profiled en dehaze verbruiken veel GPU-geheugen en kunnen tijdens runtime falen door gebrek aan beschikbaar geheugen, ook al vond de aanvankelijke geheugenplanning dat het genoeg zou moeten zijn. Wanneer dat gebeurt, was de module al enige tijd aan het rekenen en zal hij terugvallen op de CPU. Als dat vaak gebeurt, omzeil dan liever de GPU op die module de hele tijd dan tweemaal de straf te nemen.

Maar daar houdt het niet op. GPU-buffers worden ook op de GPU in leven gehouden. Het betekent dat het herstarten van een gedeeltelijke pipeline vanaf een OpenCL-module de invoer waar mogelijk rechtstreeks van de GPU haalt, zonder enige kopie vanuit RAM. Het betekent ook dat de lichtgewicht modules hun vorige GPU-buffer kunnen hergebruiken als hij past, in plaats van een nieuwe toe te wijzen. Dit alleen al opent de mogelijkheid om een realtime pipeline te hebben, nodig voor de nieuwe module Drawing, met ongeveer 60-80 ms latentie tussen penseelstreken en beeldupdates. Ik had nooit gedacht dat dit überhaupt mogelijk zou zijn.

Dezelfde geheugenhertoewijzing gebeurt in RAM aangezien Ansel nu de hele cache in zijn eigen geheugenarena  huisvest. Dit schema stelt ons niet alleen in staat om een aaneengesloten geheugenblok van het OS vooraf te reserveren bij het starten van de applicatie, wat leidt tot snellere toewijzingen, het zorgt er ook voor dat we het door de gebruiker gedefinieerde geheugenvolume niet overschrijden. Dus wanneer je besluit om 8 GB RAM aan Ansel toe te wijzen, zijn we nu in staat om ervoor te zorgen dat dit ook daadwerkelijk gebeurt: we vullen dat hele volume tot het vol is, waarna we de oudste buffers gaan recyclen. Alle pixelbuffers, module-invoer, -uitvoer, maar ook tijdelijke interne kladblokken, worden in onze geheugenarena toegewezen.

En, last but not least, er is slechts één pipelinecache voor de hele applicatie, wat betekent dat alle pipelinetypes (voorbeeld donkere kamer, hoofdafbeelding donkere kamer, miniatuurexport en bestandsexport) dezelfde cache delen. Hoewel dit beheerd moest worden voor multithreaded gelijktijdige toegang, betekent het dat als een pipeline een module-uitvoer nodig heeft die al op dezelfde grootte door een andere pipeline werd berekend, hij de cacheregel rechtstreeks kan pakken en zijn eigen herbeekening kan omzeilen.

Om hiervan te profiteren is het voorheen vaste-grootte „voorbeeld" van de donkere kamer (oftewel de verkleinde versie van de volledige afbeelding, gebruikt in de navigatiewidget, om histogrammen en kleurenpipetten te bemonsteren, en als een vluchtige „wazige" opvulling wanneer de hoofdafbeelding opnieuw wordt berekend) gewijzigd zodat het dynamisch wordt geschaald naar het „passend"-zoomniveau van de hoofdafbeelding (die in het midden van de donkere kamer wordt weergegeven). Het resultaat is dat er slechts één afbeelding berekend hoeft te worden wanneer je de donkere kamer binnenkomt, en terugzoomen naar „passend"-zoom is direct.

Maar aangezien dat vaste-grootte voorbeeld lui op veel plaatsen in de GUI werd gebruikt om cursorcoördinaten in de widgetruimte om te zetten naar RAW-beeldcoördinaten op volledige resolutie, door middel van het kopiëren en plakken van hetzelfde lelijke blok code overal (waarbij zelfs de opmerking „ik begrijp niet wat dit doet" werd meegekopieerd), moest het hele coördinatenstelsel opnieuw worden gedaan om deze wijziging te accommoderen. En, nogmaals, die coördinaten werden alleen binnen een pipeline berekend, dus de GUI moest wachten tot de pipeline de nieuwe groottes opnieuw berekende om te weten waar objecten te positioneren, wat GUI-glitches veroorzaakte, vooral bij het wijzigen van de uitsnede. Maar nu wordt dat allemaal vooraf berekend vanuit een uniforme API, dus geen dwaas kopiëren en plakken meer vermenigvuldigd met het aantal modules.

Wat dat veranderde buiten de kern

De eerste externe consequentie is dat kopieën ophielden zich voor te doen als functies. De donkere kamer heeft niet langer een speciale GUI-backbuffer nodig om weer te geven wat de renderer al heeft geproduceerd. Hij kan de gepubliceerde afbeelding rechtstreeks uit de cache pakken, er een Cairo-oppervlak op binden, en het in een paar milliseconden weergeven. Voorheen was het pad langzamer en druk met kopiëren zonder enige goede reden buiten overgeërfde ontwerpverwarring. De donkere kamer kan ook rechtstreeks controleren of een bepaalde pipeline-backbuffer up-to-date is met de huidige ontwikkelingshistorie, via checksums. Voorheen berustte dat op een „dirty"-vlag die door verschillende threads overschreven kon worden en die elk „best effort"-hertekenen van de donkere kamer verhinderde (in de zin van: sla de laatst bekende geldige backbuffer erop in afwachting van de herbeekening van de up-to-date versie). Dit was belangrijk wanneer de gebruiker moduleparameters sneller wijzigde dan de pipeline kon herberekenen: we hebben nog steeds iets nodig om de weergave te vullen om flikkeren te voorkomen.

Dezelfde logica strekt zich nu uit tot export en miniaturen, die het uiteindelijke gepubliceerde resultaat kunnen heropenen in plaats van hun eigen privé-realiteit opnieuw op te bouwen. De code voor histogram en kleurenpipet stapte ook af van het meeliften op de pipeline-uitvoering. Scopes volgen expliciete voltooiingssignalen van het voorbeeldpad, cachen hun eigen Cairo-oppervlak tegen de bronstatus, en bemonsteren rechtstreeks uit cache-gedekte backbuffers. Raw-histogram (bemonsterd na de demosaic-module) is toegevoegd aan de oude pipeline-uitvoer: schakelen tussen beide vereist geen herbeekening van de pipeline, en kleurpipetten in geen van beide evenmin. Dat is een veel saaier ontwerp, en precies daarom is het beter.

Een andere belangrijke consequentie is dat pipeline-varianten niet langer in geïsoleerde cachesilo’s leven. Voorbeeld, donkere kamer, export, miniaturen en histogramconsumenten kunnen nu cachestatus delen. Dat was de bedoeling die al lang geleden werd aangestipt in de cachecode; het kostte alleen een volledige opruiming van geldigheidstracering om het echt te maken. Zodra al die consumenten het eens zijn over dezelfde hashes, kunnen ze het eindelijk ook eens zijn over dezelfde buffers. Het voordeel is dat één pipeline de reeds berekende cacheregel van een andere pipe kan hergebruiken als hij past (dezelfde parameter, dezelfde invoer- en uitvoergrootte). Dus het begin van de pipelines van de donkere kamer is omgeschakeld naar volledige resolutie: demozaïceren en ruisonderdrukking zullen langzamer zijn bij het binnenkomen van de donkere kamer, maar daarna worden zoomen en pannen direct. En het exporteren van een afbeelding zal deze vroege fasen ook rechtstreeks uit de cache pakken. Overigens, dezelfde afbeelding tweemaal exporteren op twee verschillende resoluties berekent alleen opnieuw vanaf de schalingsmodule, aan het einde van de pipeline.

Geheugenafhandeling volgde dezelfde logica. Cacheregels werden refcounted, vergrendelbare, herbruikbare objecten in plaats van wegwerpklonten die via ad-hoc zijopslag rondgereikt werden. CPU- en GPU-paden delen nu veel meer van hetzelfde eigenaarschapsmodel. Aan de OpenCL-kant worden host- en apparaatbuffers beheerd met expliciete levensduurregels, wordt pinned memory hergebruikt in plaats van vernieuwd, en blijven RAM en VRAM gesynchroniseerd via pinned en zero-copy overdrachten waar mogelijk in plaats van gespiegeld te worden via zinloze tussentijdse kopieën. Dit maakt de GPU niet magisch sneller in rekenen. Het stopt vooral het omringende leidingwerk van het verspillen van de winst.

Het voordeel is niet alleen benchmarksnelheid. Het is ook latentie, robuustheid en energieverbruik. Het opstarten van de donkere kamer wordt korter omdat er minder kopieën en minder gedupliceerde doorgangen zijn. Zoomen, pannen, maskervoorbeeld en historienavigatie stoppen met het ongeldig maken van het halve universum enkel omdat het bewijzen van correctheid vroeger te moeilijk was. OpenCL wordt minder willekeurig omdat terugval, tegels en geheugeneigenaarschap explicieter worden vermeld. De software besteedt minder tijd aan het rondverplaatsen van pixels enkel om zichzelf gerust te stellen dat ze ergens nog steeds bestaan.

Als bijeffect is de foutafhandeling in de pipeline verbeterd. Modules die er niet in slaagden geheugen toe te wijzen gooien nu onmiddellijk een fout en breken de pipeline af. Voorheen werden toewijzingsfouten niet overal gecontroleerd, en een hele pipeline kon een NULL-buffer tot het einde meedragen… of gewoon crashen op segmentation fault-fouten. Dit wordt nu stroomopwaarts op een uniforme manier over de hele software voorkomen.

Bemonstering met de kleurenpipet en histogrammen kunnen gegevens bemonsteren zonder een herbeekening van de pipeline te activeren door rechtstreeks de cache op te halen, als de opgevraagde cacheregel bestaat. De globale scopes-gereedschapskist stelt je in staat te kiezen uit RAW RGB (bemonsterd na demosaicing) of uiteindelijke pipeline-RGB (ofwel bemonsterd na output color profile in 32-bits float ofwel in de backbuffer in 8-bits gehele getallen): van de een naar de ander wisselen herstart geen pipeline maar laadt simpelweg een andere cacheregel, en kleurpipetten gebeurt transparant op die cacheregel.

Wat er daadwerkelijk werd gerepareerd door het goed te doen

Veel zichtbare ergernissen zijn terug te voeren op dit herontwerp meer dan op welke micro-optimalisatie dan ook. De afhandeling van high-DPI ROI verbeterde omdat het geometrie-eigenaarschap duidelijker werd en de mapping van coördinaten tussen GUI en RAW-afbeelding nu in een centrale API wordt afgehandeld. De hersynchronisatie van historie naar pipeline werd minder fragiel omdat de historie ophield een incidenteel bijeffect van de GUI-stroom te zijn en een eersteklas invoer voor de planning werd. Realtime maskervoorbeeld hoeft niet langer te vechten tegen een cachemodel dat voor een ander tijdperk was ontworpen. Het verversen van het histogram werd voorspelbaar omdat het nu gepubliceerde gegevens verbruikt in plaats van te hopen dat de juiste tussentijdse buffer toevallig ergens in leven is. Oneindige lussen, verouderde cacheregels, ongeldige backbuffers en de klassieke „voorbeeld herberekende de volledige pipe vanaf module 0 zonder duidelijke reden" worden allemaal makkelijker te diagnosticeren zodra de levenscyclus expliciet is.

Dus het interessante deel hier is niet dat er één grote refactor in isolatie plaatsvond. Het is dat een lange reeks opruimingen zich eindelijk uitlijnde rond één idee: geldigheid zou vooraf berekend, benoemd en gedeeld moeten worden. Zodra dat gebeurde, volgde de rest bijna mechanisch. De cache werd centraal omdat de hashes betrouwbaar waren. Externe consumenten konden ophouden met kopiëren omdat cache-gepubliceerde buffers gezaghebbend werden. CPU- en GPU-paden konden meer status delen omdat eigenaarschap expliciet werd. En de renderer stopte met zich te gedragen als een spookhuis waar het bewegen van één schuifregelaar drie ongerelateerde subsystemen en een hertekencallback uit 2013 kon wekken.

Benchmarks

Benchmarks worden gedaan op beide applicaties, lokaal gecompileerd met een Release-build en GCC14 met behulp van hun respectieve build.sh --build-type Release-script.

Config 1
De hardware is een Thinkpad P51, met 8 × Intel Xeon CPU E3-1505M v6 @ 3.00GHz en GPU Nvidia Quadro M2200, draaiend op Fedora 41 Plasma met Wayland. De Nvidia-driverversie is 580.105.08. De Intel Xeon is een high-end CPU uitgebracht in 2015. De Quadro M2200 is een mid-range professionele CPU uitgebracht in 2017.
Config 2
De hardware is een desktop-pc met 4 × Intel Core i3-4130 en GPU AMD Radeon RX 580 Polaris 10, draaiend op Ubuntu 24.04 LTS met Wayland. De AMD-driverversie is RustiCL 25.2.8. De Core i3 is een mid-range CPU uitgebracht in 2013. De AMD Polaris 10 is een mid-high-range GPU uitgebracht in 2017.

We tonen hier de uitvoer van ansel -d perf en darktable -d perf. Zowel de config-bestanden van Ansel als van Darktable zijn ingesteld met dit script  om dezelfde config-basislijn te garanderen. De 45 Mpx testfoto is genomen van hier  en de bewerkings-XMP kan hier gedownload worden.

Initieel laden in de donkere kamer

Waarschuwing: in Ansel is het belangrijk om deze test uit te voeren zonder dat er een module gefocust is in de GUI (dat wil zeggen, uitgeklapt). In deze situatie cachet Ansel altijd de uitvoer van de vorige module, zodat we ervoor zorgen dat, wanneer er wijzigingen in die focusmodule worden gemaakt, we de berekeningen altijd vanaf de directe invoer herstarten. Maar het zo forceren van de cache veroorzaakt geheugenoverhead die zichtbaar kan zijn voor lichtgewicht modules.

Config 1

 13.690316 [dev_pixelpipe] took 0.000 secs (0.000 CPU) to load the image.
 24.201079 [dev_pixelpipe] pipeline resync with history took 0.029 secs (0.026 CPU) for pipe virtual-preview
 34.260916 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
 44.260963 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
 54.327523 [dev_pixelpipe] pipeline resync with history took 0.019 secs (0.025 CPU) for pipe preview
 64.384013 [dev_pixelpipe] took 0.056 secs (0.072 CPU) initing base buffer [preview]
 74.402520 [dev_pixelpipe] took 0.018 secs (0.031 CPU) processed `Raw settings' on GPU, blended on  [preview]
 84.421489 [dev_pixelpipe] took 0.016 secs (0.012 CPU) processed `white balance' on GPU, blended on  [preview]
 96.912680 [dev_pixelpipe] took 2.491 secs (2.470 CPU) processed `highlight reconstruction' on GPU, blended on GPU [preview]
107.167233 [dev_pixelpipe] took 0.254 secs (0.144 CPU) processed `demosaic' on GPU, blended on  [preview]
117.470521 [dev_pixelpipe] took 0.303 secs (0.173 CPU) processed `lens correction' on GPU, blended on  [preview]
127.629764 [dev_pixelpipe] took 0.159 secs (0.172 CPU) processed `Initial resampling' on GPU, blended on  [preview]
137.635593 [dev_pixelpipe] took 0.006 secs (0.006 CPU) processed `exposure' on GPU, blended on GPU [preview]
147.638110 [dev_pixelpipe] took 0.002 secs (0.001 CPU) processed `input color profile' on GPU, blended on  [preview]
157.639667 [dev_pixelpipe] took 0.002 secs (0.002 CPU) processed `color calibration' on GPU, blended on GPU [preview]
168.726634 [dev_pixelpipe] took 1.087 secs (1.090 CPU) processed `diffuse or sharpen' on GPU, blended on GPU [preview]
178.735900 [dev_pixelpipe] took 0.009 secs (0.009 CPU) processed `color balance rgb' on GPU, blended on GPU [preview]
188.742309 [dev_pixelpipe] took 0.006 secs (0.007 CPU) processed `filmic rgb' on GPU, blended on GPU [preview]
198.765175 [dev_pixelpipe] took 0.023 secs (0.029 CPU) processed `output color profile' on GPU, blended on  [preview]
208.808546 [dev_pixelpipe] took 0.043 secs (0.049 CPU) processed `dithering' on CPU, blended on  [preview]
218.820376 [dev_pixelpipe] took 0.012 secs (0.061 CPU) processed `display encoding' on CPU, blended on  [preview]
228.820439 [pixelpipe] preview internal pixel pipeline processing took 4.493 secs (4.332 CPU)
238.820483 [dev_process_preview] pipeline processing thread took 4.493 secs (4.333 CPU)
248.858716 [dev_pixelpipe] pipeline resync with history took 0.026 secs (0.032 CPU) for pipe full
258.858805 [dev_process_full] pipeline processing thread took 0.000 secs (0.000 CPU)
 110,5815 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
 210,6799 [dev_pixelpipe] took 0,018 secs (0,029 CPU) initing base buffer [full]
 310,6968 [dev_pixelpipe] took 0,017 secs (0,020 CPU) [full] processed `rawprepare' on GPU, blended on GPU
 410,7094 [dev_pixelpipe] took 0,013 secs (0,011 CPU) [full] processed `temperature' on GPU, blended on GPU
 514,4091 [dev_pixelpipe] took 3,700 secs (3,719 CPU) [full] processed `highlights' on GPU with tiling, blended on CPU
 614,8078 [resample_cl] plan 0,000 secs (0,000 CPU) resample 0,010 secs (0,002 CPU)
 714,8988 [dev_pixelpipe] took 0,490 secs (0,349 CPU) [full] processed `demosaic' on GPU, blended on GPU
 814,9094 [dev_pixelpipe] took 0,010 secs (0,001 CPU) [full] processed `lens' on GPU, blended on GPU
 914,9200 [dev_pixelpipe] took 0,010 secs (0,002 CPU) [full] processed `exposure' on GPU, blended on GPU
1014,9516 [dev_pixelpipe] took 0,032 secs (0,010 CPU) [full] processed `colorin' on GPU, blended on GPU
1114,9654 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,013 secs (0,000 GPU) [channelmixerrgb]
1214,9902 [dev_pixelpipe] took 0,039 secs (0,006 CPU) [full] processed `channelmixerrgb' on GPU, blended on GPU
1316,6800 [dev_pixelpipe] took 1,690 secs (1,745 CPU) [full] processed `diffuse' on GPU, blended on GPU
1416,6923 [dev_pixelpipe] took 0,012 secs (0,007 CPU) [full] processed `colorbalancergb' on GPU, blended on GPU
1516,7037 [dev_pixelpipe] took 0,011 secs (0,005 CPU) [full] processed `filmicrgb' on GPU, blended on GPU
1616,7100 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,006 secs (0,000 GPU) [colorout]
1716,7555 [dev_pixelpipe] took 0,052 secs (0,020 CPU) [full] processed `colorout' on GPU, blended on GPU
1816,8435 [dev_pixelpipe] took 0,088 secs (0,052 CPU) [full] processed `dither' on CPU, blended on CPU
1916,8525 [dev_pixelpipe] took 0,009 secs (0,066 CPU) [full] processed `gamma' on CPU, blended on CPU
2016,8594 [dev_process_image] pixel pipeline took 6,197 secs (6,048 CPU) processing `2022-06-17__DSC00078.arw'
21
2216,8918 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
2316,9470 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
2416,9968 [dev_pixelpipe] took 0,000 secs (0,000 CPU) initing base buffer [preview]
2516,9986 [dev_pixelpipe] took 0,002 secs (0,002 CPU) [preview] processed `rawprepare' on GPU, blended on GPU
2616,9995 [dev_pixelpipe] took 0,001 secs (0,001 CPU) [preview] processed `temperature' on GPU, blended on GPU
2717,0698 [dev_pixelpipe] took 0,070 secs (0,081 CPU) [preview] processed `highlights' on GPU, blended on GPU
2817,0811 [dev_pixelpipe] took 0,011 secs (0,005 CPU) [preview] processed `demosaic' on GPU, blended on GPU
2917,0829 [dev_pixelpipe] took 0,002 secs (0,000 CPU) [preview] processed `lens' on GPU, blended on GPU
3017,0853 [dev_pixelpipe] took 0,002 secs (0,001 CPU) [preview] processed `exposure' on GPU, blended on GPU
3117,0886 [dev_pixelpipe] took 0,003 secs (0,001 CPU) [preview] processed `colorin' on GPU, blended on GPU
3217,0915 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,003 secs (0,000 GPU) [channelmixerrgb]
3317,0952 [dev_pixelpipe] took 0,007 secs (0,002 CPU) [preview] processed `channelmixerrgb' on GPU, blended on GPU
3417,4667 [dev_pixelpipe] took 0,371 secs (0,354 CPU) [preview] processed `diffuse' on GPU, blended on GPU
3517,4702 [dev_pixelpipe] took 0,003 secs (0,001 CPU) [preview] processed `colorbalancergb' on GPU, blended on GPU
3617,4748 [dev_pixelpipe] took 0,004 secs (0,001 CPU) [preview] processed `filmicrgb' on GPU, blended on GPU
3717,4776 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,002 secs (0,000 GPU) [colorout]
3817,4939 [dev_pixelpipe] took 0,019 secs (0,009 CPU) [preview] processed `colorout' on GPU, blended on GPU
3917,5141 [dev_pixelpipe] took 0,020 secs (0,007 CPU) [preview] processed `dither' on CPU, blended on CPU
4017,5195 [dev_pixelpipe] took 0,005 secs (0,021 CPU) [preview] processed `gamma' on CPU, blended on CPU
4117,5355 [dt_ioppr_transform_image_colorspace_rgb] `Système' -> `sRVB' took 0,016 secs (0,067 CPU) [final histogram]
4217,6218 [dev_process_image] pixel pipeline took 0,625 secs (0,657 CPU) processing `2022-06-17__DSC00078.arw'
 14.146713 [dev_pixelpipe] took 0.000 secs (0.000 CPU) to load the image.
 24.642451 [dev_pixelpipe] pipeline resync with history took 0.029 secs (0.026 CPU) for pipe virtual-preview
 34.703889 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
 44.703915 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
 54.782635 [dev_pixelpipe] pipeline resync with history took 0.033 secs (0.041 CPU) for pipe preview
 64.796521 [dev_pixelpipe] took 0.014 secs (0.018 CPU) initing base buffer [preview]
 74.831601 [dev_pixelpipe] took 0.035 secs (0.061 CPU) processed `Raw settings' on CPU, blended on  [preview]
 84.862626 [dev_pixelpipe] took 0.031 secs (0.077 CPU) processed `white balance' on CPU, blended on  [preview]
 910.978874 [dev_pixelpipe] took 6.116 secs (43.505 CPU) processed `highlight reconstruction' on CPU, blended on CPU [preview]
1011.369357 [dev_pixelpipe] took 0.390 secs (2.623 CPU) processed `demosaic' on CPU, blended on  [preview]
1111.449953 [dev_pixelpipe] took 0.081 secs (0.474 CPU) processed `lens correction' on CPU, blended on  [preview]
1211.797645 [dev_pixelpipe] took 0.348 secs (2.088 CPU) processed `Initial resampling' on CPU, blended on  [preview]
1311.802788 [dev_pixelpipe] took 0.005 secs (0.025 CPU) processed `exposure' on CPU, blended on CPU [preview]
1411.807751 [dev_pixelpipe] took 0.005 secs (0.024 CPU) processed `input color profile' on CPU, blended on  [preview]
1511.877682 [dev_pixelpipe] took 0.070 secs (0.361 CPU) processed `color calibration' on CPU, blended on CPU [preview]
1615.025427 [dev_pixelpipe] took 3.148 secs (23.610 CPU) processed `diffuse or sharpen' on CPU, blended on CPU [preview]
1715.290600 [dev_pixelpipe] took 0.262 secs (1.469 CPU) processed `color balance rgb' on CPU, blended on CPU [preview]
1815.425400 [dev_pixelpipe] took 0.135 secs (0.761 CPU) processed `filmic rgb' on CPU, blended on CPU [preview]
1915.438259 [dev_pixelpipe] took 0.013 secs (0.072 CPU) processed `output color profile' on CPU, blended on  [preview]
2015.463031 [dev_pixelpipe] took 0.025 secs (0.039 CPU) processed `dithering' on CPU, blended on  [preview]
2115.474803 [dev_pixelpipe] took 0.012 secs (0.058 CPU) processed `display encoding' on CPU, blended on  [preview]
2215.474885 [pixelpipe] preview internal pixel pipeline processing took 10.692 secs (75.269 CPU)
2315.474906 [dev_process_preview] pipeline processing thread took 10.692 secs (75.269 CPU)
2415.522324 [dev_pixelpipe] pipeline resync with history took 0.037 secs (0.047 CPU) for pipe full
2515.522431 [dev_process_full] pipeline processing thread took 0.000 secs (0.000 CPU)
 14,5577 [dt_dev_load_raw] loading the image. took 0,131 secs (0,040 CPU)
 25,4913 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
 35,6087 [dev_pixelpipe] took 0,017 secs (0,029 CPU) initing base buffer [full]
 45,6491 [dev_pixelpipe] took 0,040 secs (0,120 CPU) [full] processed `rawprepare' on CPU, blended on CPU
 55,6782 [dev_pixelpipe] took 0,029 secs (0,061 CPU) [full] processed `temperature' on CPU, blended on CPU
 612,0060 [dev_pixelpipe] took 6,328 secs (45,005 CPU) [full] processed `highlights' on CPU, blended on CPU
 712,6762 [resample_plain] plan 0,001 secs (0,001 CPU) resample 0,249 secs (1,829 CPU)
 812,7230 [dev_pixelpipe] took 0,717 secs (4,499 CPU) [full] processed `demosaic' on CPU, blended on CPU
 912,7370 [dev_pixelpipe] took 0,013 secs (0,029 CPU) [full] processed `lens' on CPU, blended on CPU
1012,7487 [dev_pixelpipe] took 0,012 secs (0,029 CPU) [full] processed `exposure' on CPU, blended on CPU
1112,7637 [dev_pixelpipe] took 0,015 secs (0,045 CPU) [full] processed `colorin' on CPU, blended on CPU
1212,7693 [dt_ioppr_transform_image_colorspace] IOP_CS_LAB-->IOP_CS_RGB took 0,006 secs (0,028 CPU) [channelmixerrgb]
1312,8473 [dev_pixelpipe] took 0,084 secs (0,438 CPU) [full] processed `channelmixerrgb' on CPU, blended on CPU
1417,0570 [dev_pixelpipe] took 4,210 secs (32,406 CPU) [full] processed `diffuse' on CPU, blended on CPU
1517,3181 [dev_pixelpipe] took 0,261 secs (1,872 CPU) [full] processed `colorbalancergb' on CPU, blended on CPU
1617,4583 [dev_pixelpipe] took 0,140 secs (0,898 CPU) [full] processed `filmicrgb' on CPU, blended on CPU
1717,4634 [dt_ioppr_transform_image_colorspace] IOP_CS_RGB-->IOP_CS_LAB took 0,005 secs (0,033 CPU) [colorout]
1817,4792 [dev_pixelpipe] took 0,021 secs (0,116 CPU) [full] processed `colorout' on CPU, blended on CPU
1917,5381 [dev_pixelpipe] took 0,059 secs (0,037 CPU) [full] processed `dither' on CPU, blended on CPU
2017,5472 [dev_pixelpipe] took 0,009 secs (0,061 CPU) [full] processed `gamma' on CPU, blended on CPU
2117,5543 [dev_process_image] pixel pipeline took 11,962 secs (85,649 CPU) processing `2022-06-17__DSC00078.arw'
22
2317,5861 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
2417,6428 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
2517,6993 [dev_pixelpipe] took 0,000 secs (0,000 CPU) initing base buffer [preview]
2617,7004 [dev_pixelpipe] took 0,001 secs (0,002 CPU) [preview] processed `rawprepare' on CPU, blended on CPU
2717,7015 [dev_pixelpipe] took 0,001 secs (0,004 CPU) [preview] processed `temperature' on CPU, blended on CPU
2817,8101 [dev_pixelpipe] took 0,109 secs (0,570 CPU) [preview] processed `highlights' on CPU, blended on CPU
2917,8261 [dev_pixelpipe] took 0,016 secs (0,071 CPU) [preview] processed `demosaic' on CPU, blended on CPU
3017,8308 [dev_pixelpipe] took 0,005 secs (0,006 CPU) [preview] processed `lens' on CPU, blended on CPU
3117,8345 [dev_pixelpipe] took 0,004 secs (0,006 CPU) [preview] processed `exposure' on CPU, blended on CPU
3217,8393 [dev_pixelpipe] took 0,005 secs (0,016 CPU) [preview] processed `colorin' on CPU, blended on CPU
3317,8411 [dt_ioppr_transform_image_colorspace] IOP_CS_LAB-->IOP_CS_RGB took 0,002 secs (0,008 CPU) [channelmixerrgb]
3417,8670 [dev_pixelpipe] took 0,028 secs (0,144 CPU) [preview] processed `channelmixerrgb' on CPU, blended on CPU
3519,0763 [dev_pixelpipe] took 1,209 secs (8,091 CPU) [preview] processed `diffuse' on CPU, blended on CPU
3619,1926 [dev_pixelpipe] took 0,116 secs (0,708 CPU) [preview] processed `colorbalancergb' on CPU, blended on CPU
3719,2628 [dev_pixelpipe] took 0,070 secs (0,342 CPU) [preview] processed `filmicrgb' on CPU, blended on CPU
3819,2667 [dt_ioppr_transform_image_colorspace] IOP_CS_RGB-->IOP_CS_LAB took 0,003 secs (0,012 CPU) [colorout]
3919,2758 [dev_pixelpipe] took 0,012 secs (0,045 CPU) [preview] processed `colorout' on CPU, blended on CPU
4019,2860 [dev_pixelpipe] took 0,010 secs (0,003 CPU) [preview] processed `dither' on CPU, blended on CPU
4119,2907 [dev_pixelpipe] took 0,005 secs (0,020 CPU) [preview] processed `gamma' on CPU, blended on CPU
4219,3052 [dt_ioppr_transform_image_colorspace_rgb] `Système' -> `sRVB' took 0,014 secs (0,071 CPU) [final histogram]
4319,3928 [dev_process_image] pixel pipeline took 1,694 secs (10,211 CPU) processing `2022-06-17__DSC00078.arw'

Config 2

 136.764111 [dev_pixelpipe] took 0.313 secs (0.056 CPU) to load the image.
 237.528673 [dev_pixelpipe] pipeline resync with history took 0.044 secs (0.040 CPU) for pipe virtual-preview
 337.691646 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
 437.691699 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
 537.745145 [dev_pixelpipe] pipeline resync with history took 0.036 secs (0.043 CPU) for pipe preview
 637.916228 [dev_pixelpipe] took 0.171 secs (0.115 CPU) initing base buffer [preview]
 737.953157 [dev_pixelpipe] took 0.037 secs (0.024 CPU) processed `Raw settings' on GPU, blended on  [preview]
 837.959823 [dev_pixelpipe] took 0.007 secs (0.002 CPU) processed `white balance' on GPU, blended on  [preview]
 939.377680 [dev_pixelpipe] took 1.418 secs (0.196 CPU) processed `highlight reconstruction' on GPU, blended on GPU [preview]
1039.526422 [dev_pixelpipe] took 0.149 secs (0.039 CPU) processed `demosaic' on GPU, blended on  [preview]
1141.012847 [dev_pixelpipe] took 1.486 secs (0.271 CPU) processed `lens correction' on GPU, blended on  [preview]
1241.266624 [dev_pixelpipe] took 0.254 secs (0.110 CPU) processed `Initial resampling' on GPU, blended on  [preview]
1341.299983 [dev_pixelpipe] took 0.033 secs (0.025 CPU) processed `exposure' on GPU, blended on GPU [preview]
1441.311230 [dev_pixelpipe] took 0.011 secs (0.009 CPU) processed `input color profile' on GPU, blended on  [preview]
1541.313526 [dev_pixelpipe] took 0.002 secs (0.002 CPU) processed `color calibration' on GPU, blended on GPU [preview]
1641.471857 [dev_pixelpipe] took 0.158 secs (0.049 CPU) processed `diffuse or sharpen' on GPU, blended on GPU [preview]
1741.482377 [dev_pixelpipe] took 0.010 secs (0.008 CPU) processed `color balance rgb' on GPU, blended on GPU [preview]
1841.486457 [dev_pixelpipe] took 0.004 secs (0.007 CPU) processed `filmic rgb' on GPU, blended on GPU [preview]
1941.508325 [dev_pixelpipe] took 0.022 secs (0.018 CPU) processed `output color profile' on GPU, blended on  [preview]
2041.521171 [dev_pixelpipe] took 0.013 secs (0.016 CPU) processed `dithering' on CPU, blended on  [preview]
2141.529057 [dev_pixelpipe] took 0.008 secs (0.014 CPU) processed `display encoding' on CPU, blended on  [preview]
2241.529178 [pixelpipe] preview internal pixel pipeline processing took 3.784 secs (0.906 CPU)
2341.529291 [dev_process_preview] pipeline processing thread took 3.784 secs (0.906 CPU)
2441.576629 [dev_pixelpipe] pipeline resync with history took 0.036 secs (0.049 CPU) for pipe full
2541.579279 [dev_process_full] pipeline processing thread took 0.000 secs (0.000 CPU)
 123.6180 [dt_dev_load_raw] loading the image. took 0.290 secs (0.055 CPU)
 224.6549 [dt_dev_process_image_job] loading image. took 0.000 secs (0.000 CPU)
 324.7621 [dev_pixelpipe] took 0.023 secs (0.034 CPU) initing base buffer [full]
 424.8212 [dev_pixelpipe] took 0.059 secs (0.022 CPU) [full] processed `rawprepare' on GPU, blended on GPU
 524.8286 [dev_pixelpipe] took 0.007 secs (0.000 CPU) [full] processed `temperature' on GPU, blended on GPU
 626.6983 [dev_pixelpipe] took 1.870 secs (0.433 CPU) [full] processed `highlights' on GPU, blended on GPU
 726.7416 [resample_cl] plan 0.002 secs (0.001 CPU) resample 0.032 secs (0.000 CPU)
 826.8215 [dev_pixelpipe] took 0.123 secs (0.009 CPU) [full] processed `demosaic' on GPU, blended on GPU
 926.8260 [dev_pixelpipe] took 0.004 secs (0.001 CPU) [full] processed `lens' on GPU, blended on GPU
1026.8282 [dev_pixelpipe] took 0.002 secs (0.001 CPU) [full] processed `ashift' on GPU, blended on GPU
1126.8306 [dev_pixelpipe] took 0.002 secs (0.001 CPU) [full] processed `exposure' on GPU, blended on GPU
1226.8347 [dev_pixelpipe] took 0.004 secs (0.001 CPU) [full] processed `colorin' on GPU, blended on GPU
1326.8370 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0.002 secs (0.001 GPU) [channelmixerrgb]
1426.8384 [dev_pixelpipe] took 0.004 secs (0.001 CPU) [full] processed `channelmixerrgb' on GPU, blended on GPU
1527.3567 [dev_pixelpipe] took 0.518 secs (0.022 CPU) [full] processed `diffuse' on GPU, blended on GPU
1627.3613 [dev_pixelpipe] took 0.004 secs (0.001 CPU) [full] processed `colorbalancergb' on GPU, blended on GPU
1727.4019 [dev_pixelpipe] took 0.041 secs (0.011 CPU) [full] processed `filmicrgb' on GPU, blended on GPU
1827.4053 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0.003 secs (0.001 GPU) [colorout]
1927.4345 [dev_pixelpipe] took 0.032 secs (0.009 CPU) [full] processed `colorout' on GPU, blended on GPU
2027.4814 [dev_pixelpipe] took 0.047 secs (0.025 CPU) [full] processed `dither' on CPU, blended on CPU
2127.4962 [dev_pixelpipe] took 0.015 secs (0.045 CPU) [full] processed `gamma' on CPU, blended on CPU
2227.4990 [dev_process_image] pixel pipeline took 2.760 secs (0.618 CPU) processing `2022-06-17__DSC00078.arw'
23
2427.5249 [dt_dev_process_image_job] loading image. took 0.005 secs (0.013 CPU)
2527.5866 [dt_dev_process_image_job] loading image. took 0.000 secs (0.000 CPU)
2627.6513 [dev_pixelpipe] took 0.000 secs (0.000 CPU) initing base buffer [preview]
2727.6561 [dev_pixelpipe] took 0.005 secs (0.006 CPU) [preview] processed `rawprepare' on GPU, blended on GPU
2827.6580 [dev_pixelpipe] took 0.002 secs (0.001 CPU) [preview] processed `temperature' on GPU, blended on GPU
2927.7797 [dev_pixelpipe] took 0.122 secs (0.062 CPU) [preview] processed `highlights' on GPU, blended on GPU
3027.7845 [dev_pixelpipe] took 0.005 secs (0.002 CPU) [preview] processed `demosaic' on GPU, blended on GPU
3127.7854 [dev_pixelpipe] took 0.001 secs (0.000 CPU) [preview] processed `lens' on GPU, blended on GPU
3227.8023 [dev_pixelpipe] took 0.017 secs (0.002 CPU) [preview] processed `ashift' on GPU, blended on GPU
3327.8034 [dev_pixelpipe] took 0.001 secs (0.000 CPU) [preview] processed `exposure' on GPU, blended on GPU
3427.8058 [dev_pixelpipe] took 0.002 secs (0.000 CPU) [preview] processed `colorin' on GPU, blended on GPU
3527.8077 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0.001 secs (0.000 GPU) [channelmixerrgb]
3627.8089 [dev_pixelpipe] took 0.003 secs (0.000 CPU) [preview] processed `channelmixerrgb' on GPU, blended on GPU
3728.5157 [dev_pixelpipe] took 0.707 secs (0.076 CPU) [preview] processed `diffuse' on GPU, blended on GPU
3828.5240 [dev_pixelpipe] took 0.008 secs (0.004 CPU) [preview] processed `colorbalancergb' on GPU, blended on GPU
3928.6037 [dev_pixelpipe] took 0.079 secs (0.031 CPU) [preview] processed `filmicrgb' on GPU, blended on GPU
4028.6092 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0.005 secs (0.000 GPU) [colorout]
4128.6323 [dev_pixelpipe] took 0.028 secs (0.007 CPU) [preview] processed `colorout' on GPU, blended on GPU
4228.6675 [dev_pixelpipe] took 0.035 secs (0.010 CPU) [preview] processed `dither' on CPU, blended on CPU
4328.6881 [dev_pixelpipe] took 0.021 secs (0.066 CPU) [preview] processed `gamma' on CPU, blended on CPU
4428.8183 [dev_process_image] pixel pipeline took 1.167 secs (0.442 CPU) processing `2022-06-17__DSC00078.arw'
 113.969925 [dev_pixelpipe] took 0.271 secs (0.044 CPU) to load the image.
 214.519352 [dev_pixelpipe] pipeline resync with history took 0.039 secs (0.037 CPU) for pipe virtual-preview
 314.609258 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
 414.609291 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
 514.685917 [dev_pixelpipe] pipeline resync with history took 0.036 secs (0.048 CPU) for pipe preview
 614.724434 [dev_pixelpipe] took 0.038 secs (0.024 CPU) initing base buffer [preview]
 714.787570 [dev_pixelpipe] took 0.063 secs (0.064 CPU) processed `Raw settings' on CPU, blended on  [preview]
 814.857062 [dev_pixelpipe] took 0.069 secs (0.080 CPU) processed `white balance' on CPU, blended on  [preview]
 927.961302 [dev_pixelpipe] took 13.104 secs (32.983 CPU) processed `highlight reconstruction' on CPU, blended on CPU [preview]
1028.949286 [dev_pixelpipe] took 0.988 secs (3.057 CPU) processed `demosaic' on CPU, blended on  [preview]
1129.075925 [dev_pixelpipe] took 0.127 secs (0.326 CPU) processed `lens correction' on CPU, blended on  [preview]
1230.176998 [dev_pixelpipe] took 1.101 secs (3.061 CPU) processed `Initial resampling' on CPU, blended on  [preview]
1330.190589 [dev_pixelpipe] took 0.013 secs (0.024 CPU) processed `exposure' on CPU, blended on CPU [preview]
1430.192681 [dev_pixelpipe] took 0.002 secs (0.005 CPU) processed `input color profile' on CPU, blended on  [preview]
1530.239877 [dev_pixelpipe] took 0.047 secs (0.103 CPU) processed `color calibration' on CPU, blended on CPU [preview]
1631.944712 [dev_pixelpipe] took 1.705 secs (4.286 CPU) processed `diffuse or sharpen' on CPU, blended on CPU [preview]
1732.096771 [dev_pixelpipe] took 0.152 secs (0.407 CPU) processed `color balance rgb' on CPU, blended on CPU [preview]
1832.190015 [dev_pixelpipe] took 0.093 secs (0.228 CPU) processed `filmic rgb' on CPU, blended on CPU [preview]
1932.205505 [dev_pixelpipe] took 0.015 secs (0.028 CPU) processed `output color profile' on CPU, blended on  [preview]
2032.214424 [dev_pixelpipe] took 0.009 secs (0.011 CPU) processed `dithering' on CPU, blended on  [preview]
2132.223982 [dev_pixelpipe] took 0.009 secs (0.021 CPU) processed `display encoding' on CPU, blended on  [preview]
2232.224049 [pixelpipe] preview internal pixel pipeline processing took 17.538 secs (44.709 CPU)
2332.224090 [dev_process_preview] pipeline processing thread took 17.538 secs (44.710 CPU)
2432.276027 [dev_pixelpipe] pipeline resync with history took 0.042 secs (0.054 CPU) for pipe full
2532.276152 [dev_process_full] pipeline processing thread took 0.000 secs (0.000 CPU)
 112.5778 [dt_dev_process_image_job] loading image. took 0.000 secs (0.000 CPU)
 212.6692 [dt_dev_process_image_job] loading image. took 0.000 secs (0.000 CPU)
 312.7607 [dev_pixelpipe] took 0.018 secs (0.022 CPU) initing base buffer [full]
 412.8098 [dev_pixelpipe] took 0.049 secs (0.105 CPU) [full] processed `rawprepare' on CPU
 512.8448 [dev_pixelpipe] took 0.035 secs (0.042 CPU) [full] processed `temperature' on CPU
 625.7535 [dev_pixelpipe] took 12.909 secs (44.992 CPU) [full] processed `highlights' on CPU
 727.5129 [resample_plain] plan 0.001 secs (0.001 CPU) resample 0.732 secs (2.749 CPU)
 827.5515 [dev_pixelpipe] took 1.798 secs (6.012 CPU) [full] processed `demosaic' on CPU
 927.5571 [dev_pixelpipe] took 0.006 secs (0.005 CPU) [full] processed `lens' on CPU
1027.5603 [dev_pixelpipe] took 0.003 secs (0.003 CPU) [full] processed `ashift' on CPU
1127.5634 [dev_pixelpipe] took 0.003 secs (0.005 CPU) [full] processed `exposure' on CPU
1227.5963 [dev_pixelpipe] took 0.033 secs (0.100 CPU) [full] processed `colorin' on CPU
1327.6038 [dt_ioppr_transform_image_colorspace] IOP_CS_LAB-->IOP_CS_RGB took 0.007 secs (0.018 CPU) [channelmixerrgb]
1427.6464 [dev_pixelpipe] took 0.050 secs (0.163 CPU) [full] processed `channelmixerrgb' on CPU
1531.0132 [dev_pixelpipe] took 3.367 secs (12.611 CPU) [full] processed `diffuse' on CPU
1631.1921 [dev_pixelpipe] took 0.179 secs (0.647 CPU) [full] processed `colorbalancergb' on CPU
1731.3065 [dev_pixelpipe] took 0.114 secs (0.406 CPU) [full] processed `filmicrgb' on CPU
1831.3321 [dt_ioppr_transform_image_colorspace] IOP_CS_RGB-->IOP_CS_LAB took 0.025 secs (0.091 CPU) [colorout]
1931.3475 [dev_pixelpipe] took 0.041 secs (0.124 CPU) [full] processed `colorout' on CPU
2031.3754 [dev_pixelpipe] took 0.028 secs (0.020 CPU) [full] processed `dither' on CPU
2131.3849 [dev_pixelpipe] took 0.009 secs (0.034 CPU) [full] processed `gamma' on CPU
2231.3870 [dev_process_image] pixel pipeline took 18.644 secs (65.292 CPU) processing `2022-06-17__DSC00078.arw'
23
2431.4040 [dt_dev_process_image_job] loading image. took 0.000 secs (0.000 CPU)
2531.5018 [dt_dev_process_image_job] loading image. took 0.000 secs (0.000 CPU)
2631.5722 [dev_pixelpipe] took 0.000 secs (0.000 CPU) initing base buffer [preview]
2731.5824 [dev_pixelpipe] took 0.010 secs (0.014 CPU) [preview] processed `rawprepare' on CPU
2831.5861 [dev_pixelpipe] took 0.004 secs (0.008 CPU) [preview] processed `temperature' on CPU
2932.7796 [dev_pixelpipe] took 1.193 secs (4.129 CPU) [preview] processed `highlights' on CPU
3032.8917 [dev_pixelpipe] took 0.112 secs (0.387 CPU) [preview] processed `demosaic' on CPU
3132.9099 [dev_pixelpipe] took 0.018 secs (0.031 CPU) [preview] processed `lens' on CPU
3232.9433 [dev_pixelpipe] took 0.033 secs (0.050 CPU) [preview] processed `ashift' on CPU
3332.9610 [dev_pixelpipe] took 0.018 secs (0.023 CPU) [preview] processed `exposure' on CPU
3433.1087 [dev_pixelpipe] took 0.148 secs (0.532 CPU) [preview] processed `colorin' on CPU
3533.1362 [dt_ioppr_transform_image_colorspace] IOP_CS_LAB-->IOP_CS_RGB took 0.027 secs (0.096 CPU) [channelmixerrgb]
3633.3353 [dev_pixelpipe] took 0.227 secs (0.825 CPU) [preview] processed `channelmixerrgb' on CPU
3755.6386 [dev_pixelpipe] took 22.303 secs (82.427 CPU) [preview] processed `diffuse' on CPU
3856.4763 [dev_pixelpipe] took 0.837 secs (3.180 CPU) [preview] processed `colorbalancergb' on CPU
3957.0002 [dev_pixelpipe] took 0.523 secs (1.966 CPU) [preview] processed `filmicrgb' on CPU
4057.1225 [dt_ioppr_transform_image_colorspace] IOP_CS_RGB-->IOP_CS_LAB took 0.122 secs (0.437 CPU) [colorout]
4157.1852 [dev_pixelpipe] took 0.184 secs (0.637 CPU) [preview] processed `colorout' on CPU
4257.2043 [dev_pixelpipe] took 0.019 secs (0.018 CPU) [preview] processed `dither' on CPU
4357.2471 [dev_pixelpipe] took 0.043 secs (0.155 CPU) [preview] processed `gamma' on CPU
4457.4090 [dev_process_image] pixel pipeline took 25.837 secs (94.647 CPU) processing `2022-06-17__DSC00078.arw'

Rapport

Allereerst, bij het binnenkomen van de donkere kamer, berekent Darktable 2 pipelines voor hetzelfde resultaat als Ansel, dat er slechts één berekent. Dus, ongeacht de werkelijke looptijden, is het al half nutteloze berekeningen.

Vervolgens berekent Ansel de afbeelding op volledige resolutie tot en met de initial resampling-module, terwijl Darktable het alleen tot vóór demosaic doet. Dit is belangrijk voor de vergelijking.

Config 1 (Intel Xeon, Nvidia Quadro)

SoftwareGPUCPU
Ansel4.493 s10.692 s
Darktable 5.4.16.822 s13.66 s

Config 2 (Intel i3, AMD Radeon)

SoftwareGPUCPU
Ansel3.784 s17.538 s
Darktable 5.4.13.927 s44.481 s

Op config 1 slaagt Darktable erin langzamer te zijn dan Ansel op GPU, zelfs als we alleen naar de rendering van de enkele main pipeline kijken en zelfs met het eerder verkleinen van de foto naar weergaveresolutie in de pipeline. Maar we zien feitelijk hetzelfde effect op CPU, ondanks alle vermeende „optimalisaties" die rond 2023-2024 in Darktable op CPU-only-modules werden gedaan. Al met al zal Darktable je computer 2,3 tot 3,0 s langer bevriezen.

Op config 2 vertoont het CPU-pad een straf van 0,8 s voor Ansel op alleen de main pipeline. De AMD-GPU vertoont een slechte klap op de lens correction-module, die op Ansel op volledige resolutie verwerkt terwijl hij in Darktable op schermresolutie verwerkt. Rekening houdend met de tweede pipeline die Darktable draait, is Ansel 0,14 s sneller op GPU. Op CPU echter bevriest Darktable de machine nu 27,07 s langer vanwege dat gedupliceerde pipelinewerk. Hoe dan ook, de trage modules bevinden zich aan het begin van de pipeline en zullen voor de hele sessie niet opnieuw berekend worden.

Dat geeft ons de volgende module-vergelijkingen naast elkaar. We vergelijken alleen modules die op dezelfde resolutie draaien voor alleen de pipeline van de hoofdafbeelding. In het tabblad met gemiddelden worden factoren gemiddeld met een geometrisch gemiddelde en relatieve verschillen met een harmonisch gemiddelde:

Module / chipAnsel MasterDarktable 5.4.1Ansel speed-up
Raw settings* / CPU35 ms40 ms×1.14 / +13 %
Raw settings* / GPU18 ms17 ms×0.96 / -5.9 %
White balance* / CPU31 ms29 ms×0.94 / -6.9 %
White balance* / GPU16 ms13 ms×0.81 / -23 %
Highlights reconstruction* / CPU6.12 s6.33 s×1.03 / +3.4 %
Highlights reconstruction* / GPU2.49 s3.70 s×1.49 / +33 %
Demosaic* / CPU348 ms717 ms×2.06 / +52 %
Demosaic* / GPU254 ms490 ms×1.93 / +48 %
Exposure / CPU5 ms12 ms×2.4 / +58 %
Exposure / GPU6 ms10 ms×1.67 / +40 %
Input color profile / CPU3 ms15 ms×3 / +67 %
Input color profile / GPU2 ms32 ms×16 / +94 %
Color calibration / CPU70 ms84 ms×1.20 / +25 %
Color calibration / GPU1 ms39 ms×39 / +97 %
Diffuse or sharpen / CPU3.15 s4.21 s×1.34 / +25.2 %
Diffuse or sharpen / GPU1.09 s1.69 s×1.55 / +35 %
Color balance RGB / CPU262 ms261 ms×1.00 / -0.4 %
Color balance RGB / GPU9 ms12 ms×1.33 / +25 %
Filmic RGB / CPU137 ms140 ms×1.02 / +2.1 %
Filmic RGB / GPU6 ms11 ms×1.83 / +45 %
Output color profile / CPU13 ms21 ms×1.62 / +38 %
Output color profile / GPU23 ms52 ms×2.26 / +56 %
Dithering (CPU only) / CPU pipeline24 ms59 ms×2.46 / +59 %
Dithering (CPU only) / GPU pipeline43 ms88 ms×2.05 / +51 %
Gamma / display encoding (CPU only) / GPU pipeline12 ms9 ms×0.75 / -33 %
Gamma / display encoding (CPU only) / CPU pipeline12 ms9 ms×0.75 / -33 %

*: modules die op beide applicaties op volledige resolutie draaien.

Module / chipAnsel MasterDarktable 5.4.1Ansel speed-up
Raw settings* / CPU63 ms49 ms×0.78 / -29 %
Raw settings* / GPU37 ms59 ms×1.59 / +37 %
White balance* / CPU69 ms35 ms×0.5 / -97 %
White balance* / GPU7 ms7 ms×1 / 0 %
Highlights reconstruction* / CPU13.10 s12.91 s×0.99 / -1.5 %
Highlights reconstruction* / GPU1.42 s1.87 s×1.32 / +24 %
Demosaic* / CPU0.99 s1.80 s×1.82 / +45 %
Demosaic* / GPU149 ms123 ms×0.83 / -21 %
Exposure / CPU13 ms3 ms×0.23 / -333 %
Exposure / GPU33 ms2 ms×0.06 / -1550 %
Input color profile / CPU2 ms33 ms×16.5 / +94 %
Input color profile / GPU11 ms4 ms×0.36 / -175 %
Color calibration / CPU47 ms50 ms×1.06 / 6 %
Color calibration / GPU2 ms4 ms×2 / +50 %
Diffuse or sharpen / CPU1.71 s3.37 s×1.97 / +49.4 %
Diffuse or sharpen / GPU158 ms518 ms×3.28 / +70 %
Color balance RGB / CPU152 ms179 ms×1.18 / +15 %
Color balance RGB / GPU10 ms4 ms×0.40 / -150 %
Filmic RGB / CPU93 ms114 ms×1.23 / +18 %
Filmic RGB / GPU4 ms41 ms×10.26 / +90 %
Output color profile / CPU15 ms41 ms×2.73 / +63 %
Output color profile / GPU22 ms32 ms×1.45 / +31 %
Dithering (CPU only) / CPU pipeline9 ms28 ms×3.62 / +72 %
Dithering (CPU only) / GPU pipeline13 ms47 ms×2.76 / +64 %
Gamma / display encoding (CPU only) / CPU pipeline9 ms9 ms×1.0 / 0 %
Gamma / display encoding (CPU only) / GPU pipeline8 ms15 ms×1.88 / +47 %

*: modules die op beide applicaties op volledige resolutie draaien.

Gemiddelde over config 1 en 2. Factoren worden gemiddeld met een geometrisch gemiddelde, en relatieve verschillen met een harmonisch gemiddelde.

Module / chipAnsel speed-upAnsel code
Raw settings* / CPU×0.94Custom (manually vectorized)
Raw settings* / GPU×1.23Same as DT 5.4.1
White balance* / CPU×0.69Custom (manually vectorized)
White balance* / GPU×0.97Same as DT 5.4.1
Highlights reconstruction* / CPU×1.1Custom (manually vectorized)
Highlights reconstruction* / GPU×1.4Custom
Demosaic* / CPU×1.94Same as DT 4.0
Demosaic* / GPU×1.26Custom
Exposure / CPU×0.74Custom (manually vectorized)
Exposure / GPU×0.32Same as DT 4.0
Input color profile / CPU×7.04Custom (manually vectorized)
Input color profile / GPU×2.41Custom
Color calibration / CPU×1.13Custom (manually vectorized)
Color calibration / GPU×8.83Same as DT 4.0
Diffuse or sharpen / CPU×1.08Custom
Diffuse or sharpen / GPU×2.26Custom
Color balance RGB / CPU×1.08Custom (manually vectorized)
Color balance RGB / GPU×0.73Custom
Filmic RGB / CPU×1.13Custom (manually vectorized)
Filmic RGB / GPU×4.33Custom
Output color profile / CPU×2.10Custom (manually vectorized)
Output color profile / GPU×1.81Custom
Dithering (CPU only) / CPU pipeline×2.71Same as DT 4.0
Dithering (CPU only) / GPU pipeline×2.72Same as DT 4.0
Gamma / display encoding (CPU only) / CPU pipeline×0.87Same as DT 5.4.1
Gamma / display encoding (CPU only) / GPU pipeline×1.63Same as DT 5.4.1

*: modules die op beide applicaties op volledige resolutie draaien.

Relatieve snelheid per module (GPU). Hoger is beter.

Ansel vertoont GPU-prestatieverbeteringen, zelfs op kernels die sinds Darktable 4.0 niet veranderd zijn. De versnellingen die we zien zijn duidelijk het voordeel van het geheugenbeheer op hoog niveau, met behulp van pinned OpenCL memory of gewone device-only geheugenbuffers waar relevant.

Over alle modules is Ansel 1,6 keer sneller dan Darktable op GPU (geometrisch gemiddelde).

Relatieve snelheid per module (CPU). Hoger is beter.

Op CPU zijn de zaken genuanceerder.

Darktable 5.x zou CPU-optimalisaties voor dithering en demosaicing (RCD) ontvangen hebben, maar toch presteren beide modules slechter dan die van Ansel op beide configs.

Ansel heeft handmatig gevectoriseerde CPU-pixelcode voor color balance RGB, color calibration, input/output color profile, raw settings, white balance, exposure en filmic, terwijl die van Darktable compilerhints gebruikt om vectorisatie te bereiken. Ze presteren allemaal beter dan die van Darktable op de Intel Xeon. Op de Intel i3, voor basis kleurmatrixwerk, presteert Ansel (veel) beter, maar het schaadt lichtjes basismodules als raw settings, exposure of white balance.

Diffuse or sharpen zou nog steeds dezelfde Darktable 4.0-code moeten gebruiken op Ansel en op Darktable 5.4, maar Ansel is sneller op beide configs, wat het voordeel toont van het gebruik van onze eigen vooraf toegewezen geheugenarray voor de cache, en het toewijzen van geheugenbuffers buiten de OS-circuitry. Dit toont aan dat optimaliseren op moduleniveau de verkeerde scope is, en dat de globale pipeline eerst een revisie nodig had.

Maar het is natuurlijk makkelijker om module-gewijze optimalisaties aan te pakken omdat modules… modulair zijn, dat wil zeggen zelfomsloten en zelfstandig. Er is weinig kans om de software als geheel te verknoeien wanneer je aan modules werkt omdat ze geïsoleerd zijn van de rest. Applicatie-globale architectuurwijzigingen daarentegen zijn gevaarlijk, ingewikkeld en veeleisend. En ze dwingen af om de ontwikkeling van welke nieuwe module dan ook stop te zetten terwijl de architectuur gestabiliseerd wordt. Wat Darktable nooit de discipline zal hebben om te doen, omdat het project onbeheerd is en willekeurige pull requests op Github op willekeurige momenten opduiken van willekeurige bijdragers.

Over alle modules is Ansel 1,8 keer sneller dan Darktable op CPU (geometrisch gemiddelde).

Als we de GPU- en CPU-paden over beide configs combineren, is het openen van de donkere kamer 1,5 keer sneller op Ansel (geometrisch gemiddelde).

Zoomen op 100%

In de donkere kamer, vanaf de „zoom tot passend"-grootte, zoom in één klik naar 100% met de middelste knop van de muis

 112.083270 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
 212.111607 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe full
 312.177976 [dev_pixelpipe] took 0.066 secs (0.095 CPU) processed `Initial resampling' on GPU, blended on  [full]
 412.179976 [dev_pixelpipe] took 0.002 secs (0.002 CPU) processed `exposure' on GPU, blended on GPU [full]
 512.183194 [dev_pixelpipe] took 0.003 secs (0.005 CPU) processed `input color profile' on GPU, blended on  [full]
 612.185327 [dev_pixelpipe] took 0.002 secs (0.002 CPU) processed `color calibration' on GPU, blended on GPU [full]
 714.887725 [dev_pixelpipe] took 2.702 secs (2.705 CPU) processed `diffuse or sharpen' on GPU, blended on GPU [full]
 814.899213 [dev_pixelpipe] took 0.011 secs (0.013 CPU) processed `color balance rgb' on GPU, blended on GPU [full]
 914.907159 [dev_pixelpipe] took 0.008 secs (0.008 CPU) processed `filmic rgb' on GPU, blended on GPU [full]
1014.940617 [dev_pixelpipe] took 0.033 secs (0.039 CPU) processed `output color profile' on GPU, blended on  [full]
1115.005967 [dev_pixelpipe] took 0.065 secs (0.057 CPU) processed `dithering' on CPU, blended on  [full]
1215.030966 [dev_pixelpipe] took 0.025 secs (0.036 CPU) processed `display encoding' on GPU, blended on  [full]
1315.031021 [pixelpipe] full internal pixel pipeline processing took 2.919 secs (2.963 CPU)
1415.031080 [dev_process_full] pipeline processing thread took 2.919 secs (2.963 CPU)
 189,3415 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
 289,3440 [dev_pixelpipe] took 0,002 secs (0,001 CPU) initing base buffer [full]
 389,3544 [dev_pixelpipe] took 0,010 secs (0,008 CPU) [full] processed `rawprepare' on GPU, blended on GPU
 489,3573 [dev_pixelpipe] took 0,003 secs (0,001 CPU) [full] processed `temperature' on GPU, blended on GPU
 589,8611 [dev_pixelpipe] took 0,504 secs (0,511 CPU) [full] processed `highlights' on GPU, blended on GPU
 689,9200 [dev_pixelpipe] took 0,059 secs (0,023 CPU) [full] processed `demosaic' on GPU, blended on GPU
 789,9251 [dev_pixelpipe] took 0,005 secs (0,003 CPU) [full] processed `lens' on GPU, blended on GPU
 889,9346 [dev_pixelpipe] took 0,009 secs (0,003 CPU) [full] processed `exposure' on GPU, blended on GPU
 989,9480 [dev_pixelpipe] took 0,013 secs (0,003 CPU) [full] processed `colorin' on GPU, blended on GPU
1089,9576 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,009 secs (0,002 GPU) [channelmixerrgb]
1189,9736 [dev_pixelpipe] took 0,026 secs (0,008 CPU) [full] processed `channelmixerrgb' on GPU, blended on GPU
1294,9286 [dev_pixelpipe] took 4,955 secs (5,096 CPU) [full] processed `diffuse' on GPU, blended on GPU
1394,9528 [dev_pixelpipe] took 0,024 secs (0,007 CPU) [full] processed `colorbalancergb' on GPU, blended on GPU
1494,9836 [dev_pixelpipe] took 0,031 secs (0,009 CPU) [full] processed `filmicrgb' on GPU, blended on GPU
1594,9925 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,009 secs (0,000 GPU) [colorout]
1695,0700 [dev_pixelpipe] took 0,086 secs (0,028 CPU) [full] processed `colorout' on GPU, blended on GPU
1795,2184 [dev_pixelpipe] took 0,148 secs (0,093 CPU) [full] processed `dither' on CPU, blended on CPU
1895,2404 [dev_pixelpipe] took 0,022 secs (0,104 CPU) [full] processed `gamma' on CPU, blended on CPU
1995,2537 [dev_process_image] pixel pipeline took 5,912 secs (5,904 CPU) processing `2022-06-17__DSC00078.arw'
2095,2634 [dev_process_image] pixel pipeline took 0,010 secs (0,004 CPU) processing `2022-06-17__DSC00078.arw'

Omdat Ansel de vroege fasen van de pipeline op volledige resolutie verwerkt, worden ze ook op volledige resolutie gecacht, wat betekent dat pannen en zoomen de cache stroomopwaarts van de initial resampling-module ophalen, en alleen verderop opnieuw berekenen. Dus het duurt 2,9 s om te renderen. Darktable daarentegen heeft een niet-werkende cache, dus het herberekent alles vanaf het begin, wat 5,9 s duurt om hetzelfde te renderen. Het is een ×2 prestatiestraf voor Darktable.

Pannen op 100%

 155.456510 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe full
 255.536149 [dev_pixelpipe] took 0.080 secs (0.121 CPU) processed `Initial resampling' on GPU, blended on  [full]
 355.541720 [dev_pixelpipe] took 0.005 secs (0.003 CPU) processed `exposure' on GPU, recycled cacheline, blended on GPU [full]
 455.551346 [dev_pixelpipe] took 0.009 secs (0.006 CPU) processed `input color profile' on GPU, recycled cacheline, blended on  [full]
 555.559669 [dev_pixelpipe] took 0.008 secs (0.005 CPU) processed `color calibration' on GPU, recycled cacheline, blended on GPU [full]
 658.290943 [dev_pixelpipe] took 2.731 secs (2.819 CPU) processed `diffuse or sharpen' on GPU, blended on GPU [full]
 758.310400 [dev_pixelpipe] took 0.016 secs (0.017 CPU) processed `color balance rgb' on GPU, recycled cacheline, blended on GPU [full]
 858.322514 [dev_pixelpipe] took 0.012 secs (0.014 CPU) processed `filmic rgb' on GPU, recycled cacheline, blended on GPU [full]
 958.364803 [dev_pixelpipe] took 0.042 secs (0.054 CPU) processed `output color profile' on GPU, blended on  [full]
1058.411730 [dev_pixelpipe] took 0.045 secs (0.052 CPU) processed `dithering' on CPU, recycled cacheline, blended on  [full]
1158.440432 [dev_pixelpipe] took 0.029 secs (0.042 CPU) processed `display encoding' on GPU, blended on  [full]
1258.440478 [pixelpipe] full internal pixel pipeline processing took 2.984 secs (3.133 CPU)
1358.440516 [dev_process_full] pipeline processing thread took 2.984 secs (3.133 CPU)
 1253,1082 [dev_pixelpipe] took 0,003 secs (0,004 CPU) initing base buffer [full]
 2253,1132 [dev_pixelpipe] took 0,005 secs (0,004 CPU) [full] processed `rawprepare' on GPU, blended on GPU
 3253,1152 [dev_pixelpipe] took 0,002 secs (0,001 CPU) [full] processed `temperature' on GPU, blended on GPU
 4253,5743 [dev_pixelpipe] took 0,459 secs (0,441 CPU) [full] processed `highlights' on GPU, blended on GPU
 5253,6257 [dev_pixelpipe] took 0,051 secs (0,022 CPU) [full] processed `demosaic' on GPU, blended on GPU
 6253,6307 [dev_pixelpipe] took 0,005 secs (0,002 CPU) [full] processed `lens' on GPU, blended on GPU
 7253,6394 [dev_pixelpipe] took 0,009 secs (0,003 CPU) [full] processed `exposure' on GPU, blended on GPU
 8253,6521 [dev_pixelpipe] took 0,013 secs (0,003 CPU) [full] processed `colorin' on GPU, blended on GPU
 9253,6610 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,008 secs (0,001 GPU) [channelmixerrgb]
10253,6760 [dev_pixelpipe] took 0,024 secs (0,005 CPU) [full] processed `channelmixerrgb' on GPU, blended on GPU
11258,6306 [dev_pixelpipe] took 4,954 secs (4,882 CPU) [full] processed `diffuse' on GPU, blended on GPU
12258,6548 [dev_pixelpipe] took 0,024 secs (0,005 CPU) [full] processed `colorbalancergb' on GPU, blended on GPU
13258,6857 [dev_pixelpipe] took 0,031 secs (0,009 CPU) [full] processed `filmicrgb' on GPU, blended on GPU
14258,6945 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,009 secs (0,000 GPU) [colorout]
15258,7725 [dev_pixelpipe] took 0,087 secs (0,034 CPU) [full] processed `colorout' on GPU, blended on GPU
16258,9198 [dev_pixelpipe] took 0,147 secs (0,086 CPU) [full] processed `dither' on CPU, blended on CPU
17258,9373 [dev_pixelpipe] took 0,017 secs (0,110 CPU) [full] processed `gamma' on CPU, blended on CPU
18258,9407 [dev_process_image] pixel pipeline took 5,859 secs (5,614 CPU) processing `2022-06-17__DSC00078.arw'
19258,9735 [dev_process_image] pixel pipeline took 0,033 secs (0,014 CPU) processing `2022-06-17__DSC00078.arw'

Pannen leidt tot dezelfde situatie als zoomen: Ansel heeft de afbeelding op volledige resolutie in de cache, dus we herberekenen vanaf de initiële resampling, wat 3 s duurt. Darktable kan geen cache goed beheren, dus je zit vast aan een volledige herberekening en 5,9 s bevroren computer.

Heen en weer gaan naar de lichttafel

1184.536988 [dev_pixelpipe] took 0.000 secs (0.000 CPU) to load the image.
2184.574776 [dev_pixelpipe] pipeline resync with history took 0.019 secs (0.016 CPU) for pipe virtual-preview
3185.012395 [dev_pixelpipe] pipeline resync with history took 0.020 secs (0.017 CPU) for pipe virtual-preview
4185.046379 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
5185.046424 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe virtual-preview
6185.049883 [dev_pixelpipe] pipeline resync with history took 0.026 secs (0.049 CPU) for pipe preview
7185.049931 [dev_pixelpipe] pipeline resync with history took 0.000 secs (0.000 CPU) for pipe preview
8185.068516 [dev_pixelpipe] pipeline resync with history took 0.019 secs (0.020 CPU) for pipe full
9185.068568 [dev_process_full] pipeline processing thread took 0.000 secs (0.000 CPU)
 13324,5295 [histogram] took 0,006 secs (0,005 CPU) scope draw
 23324,5837 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
 33324,6371 [dev_process_image] pixel pipeline took 0,002 secs (0,001 CPU) processing `2022-06-17__DSC00078.arw'
 4
 53324,7352 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
 63324,8074 [dev_pixelpipe] took 0,000 secs (0,000 CPU) initing base buffer [preview]
 73324,8155 [dev_pixelpipe] took 0,008 secs (0,005 CPU) [preview] processed `rawprepare' on GPU, blended on GPU
 83324,8165 [dev_pixelpipe] took 0,001 secs (0,001 CPU) [preview] processed `temperature' on GPU, blended on GPU
 93324,8178 [dev_pixelpipe] took 0,001 secs (0,003 CPU) [preview] processed `highlights' on GPU, blended on GPU
103324,8337 [dev_pixelpipe] took 0,016 secs (0,021 CPU) [preview] processed `demosaic' on GPU, blended on GPU
113324,8351 [dev_pixelpipe] took 0,001 secs (0,002 CPU) [preview] processed `lens' on GPU, blended on GPU
123324,8387 [dev_pixelpipe] took 0,003 secs (0,013 CPU) [preview] processed `exposure' on GPU, blended on GPU
133324,8440 [dev_pixelpipe] took 0,005 secs (0,015 CPU) [preview] processed `colorin' on GPU, blended on GPU
143324,8491 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,005 secs (0,012 GPU) [channelmixerrgb]
153324,8545 [dev_pixelpipe] took 0,010 secs (0,019 CPU) [preview] processed `channelmixerrgb' on GPU, blended on GPU
163325,6440 [dev_pixelpipe] took 0,789 secs (0,921 CPU) [preview] processed `diffuse' on GPU, blended on GPU
173325,6482 [dev_pixelpipe] took 0,004 secs (0,003 CPU) [preview] processed `colorbalancergb' on GPU, blended on GPU
183325,6534 [dev_pixelpipe] took 0,005 secs (0,003 CPU) [preview] processed `filmicrgb' on GPU, blended on GPU
193325,6569 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,003 secs (0,002 GPU) [colorout]
203325,6747 [dev_pixelpipe] took 0,021 secs (0,008 CPU) [preview] processed `colorout' on GPU, blended on GPU
213325,6979 [dev_pixelpipe] took 0,023 secs (0,009 CPU) [preview] processed `dither' on CPU, blended on CPU
223325,7061 [dev_pixelpipe] took 0,008 secs (0,029 CPU) [preview] processed `gamma' on CPU, blended on CPU
233325,7263 [dt_ioppr_transform_image_colorspace_rgb] `Système' -> `sRVB' took 0,020 secs (0,068 CPU) [final histogram]
243325,7357 [dev_process_image] pixel pipeline took 0,935 secs (1,152 CPU) processing `2022-06-17__DSC00078.arw'

De pipelinecache van Ansel overleeft de pipelines zelf, wat betekent dat het verlaten van de donkere kamer en het opnieuw betreden ervan bijna onmiddellijk gaat: het duurt slechts 60 ms om alle pipelines opnieuw te synchroniseren met de ontwikkelingsgeschiedenis en te ontdekken dat we de pipeline-uitvoer al in de cache hebben via de checksum. Merk op dat er hier geen enkele speciale afhandeling is, het is generiek cachegedrag.

Voor Darktable werkt het bijna voor de hoofdafbeelding, maar niet voor de voorbeeldafbeelding, dus je zit vast aan 1 s nutteloze herberekening. Aangezien dit werkt op de ene pipe maar niet op de andere, durf ik te wedden dat het via speciale gevallen wordt afgehandeld. Vergeleken met Ansel is dat een prestatieverlies van ×1,75.

Een module midden in de pipeline uitschakelen

Ik heb diffuse or sharpen uitgeschakeld, ingezoomd op “fill”-grootte.

 1124.206298 [dev_pixelpipe] pipeline resync with history took 0.011 secs (0.010 CPU) for pipe virtual-preview
 2124.237640 [dev_pixelpipe] pipeline resync with history took 0.011 secs (0.028 CPU) for pipe preview
 3124.290940 [dev_pixelpipe] took 0.023 secs (0.028 CPU) processed `color balance rgb' on GPU, recycled cacheline, blended on GPU [preview]
 4124.303176 [dev_pixelpipe] took 0.012 secs (0.012 CPU) processed `filmic rgb' on GPU, recycled cacheline, blended on GPU [preview]
 5124.331334 [dev_pixelpipe] took 0.028 secs (0.030 CPU) processed `output color profile' on GPU, blended on  [preview]
 6124.370193 [darkroom] took 0.007 secs (0.011 CPU) redraw
 7124.382425 [dev_pixelpipe] took 0.051 secs (0.055 CPU) processed `dithering' on CPU, blended on  [preview]
 8124.410053 [dev_pixelpipe] took 0.028 secs (0.028 CPU) processed `display encoding' on GPU, blended on  [preview]
 9124.410088 [pixelpipe] preview internal pixel pipeline processing took 0.172 secs (0.197 CPU)
10124.410115 [dev_process_preview] pipeline processing thread took 0.172 secs (0.197 CPU)
11124.433186 [dev_pixelpipe] pipeline resync with history took 0.013 secs (0.017 CPU) for pipe full
12124.433286 [dev_process_full] pipeline processing thread took 0.000 secs (0.000 CPU)
 1300,9771 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
 2301,0564 [dev_pixelpipe] took 0,016 secs (0,028 CPU) initing base buffer [full]
 3301,0936 [dev_pixelpipe] took 0,037 secs (0,037 CPU) [full] processed `rawprepare' on GPU, blended on GPU
 4301,1102 [dev_pixelpipe] took 0,017 secs (0,017 CPU) [full] processed `temperature' on GPU, blended on GPU
 5304,8700 [dev_pixelpipe] took 3,760 secs (3,786 CPU) [full] processed `highlights' on GPU with tiling, blended on CPU
 6305,2630 [resample_cl] plan 0,001 secs (0,000 CPU) resample 0,010 secs (0,001 CPU)
 7305,3543 [dev_pixelpipe] took 0,484 secs (0,284 CPU) [full] processed `demosaic' on GPU, blended on GPU
 8305,3648 [dev_pixelpipe] took 0,010 secs (0,002 CPU) [full] processed `lens' on GPU, blended on GPU
 9305,3764 [dev_pixelpipe] took 0,012 secs (0,001 CPU) [full] processed `exposure' on GPU, blended on GPU
10305,4083 [dev_pixelpipe] took 0,032 secs (0,007 CPU) [full] processed `colorin' on GPU, blended on GPU
11305,4220 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,013 secs (0,001 GPU) [channelmixerrgb]
12305,4460 [dev_pixelpipe] took 0,038 secs (0,008 CPU) [full] processed `channelmixerrgb' on GPU, blended on GPU
13307,1388 [dev_pixelpipe] took 1,693 secs (1,645 CPU) [full] processed `diffuse' on GPU, blended on GPU
14307,1500 [dev_pixelpipe] took 0,011 secs (0,003 CPU) [full] processed `colorbalancergb' on GPU, blended on GPU
15307,1612 [dev_pixelpipe] took 0,011 secs (0,003 CPU) [full] processed `filmicrgb' on GPU, blended on GPU
16307,1675 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,006 secs (0,001 GPU) [colorout]
17307,2185 [dev_pixelpipe] took 0,057 secs (0,020 CPU) [full] processed `colorout' on GPU, blended on GPU
18307,3095 [dev_pixelpipe] took 0,091 secs (0,056 CPU) [full] processed `dither' on CPU, blended on CPU
19307,3235 [dev_pixelpipe] took 0,014 secs (0,065 CPU) [full] processed `gamma' on CPU, blended on CPU
20307,3333 [dev_process_image] pixel pipeline took 6,293 secs (5,969 CPU) processing `2022-06-17__DSC00078.arw'
21307,3843 [dev_process_image] pixel pipeline took 0,051 secs (0,018 CPU) processing `2022-06-17__DSC00078.arw'
22
23307,4258 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
24307,4875 [dev_pixelpipe] took 0,000 secs (0,000 CPU) initing base buffer [preview]
25307,4895 [dev_pixelpipe] took 0,002 secs (0,002 CPU) [preview] processed `rawprepare' on GPU, blended on GPU
26307,4906 [dev_pixelpipe] took 0,001 secs (0,001 CPU) [preview] processed `temperature' on GPU, blended on GPU
27307,5609 [dev_pixelpipe] took 0,070 secs (0,072 CPU) [preview] processed `highlights' on GPU, blended on GPU
28307,5722 [dev_pixelpipe] took 0,011 secs (0,005 CPU) [preview] processed `demosaic' on GPU, blended on GPU
29307,5740 [dev_pixelpipe] took 0,002 secs (0,000 CPU) [preview] processed `lens' on GPU, blended on GPU
30307,5765 [dev_pixelpipe] took 0,002 secs (0,001 CPU) [preview] processed `exposure' on GPU, blended on GPU
31307,5798 [dev_pixelpipe] took 0,003 secs (0,002 CPU) [preview] processed `colorin' on GPU, blended on GPU
32307,5827 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,002 secs (0,002 GPU) [channelmixerrgb]
33307,5864 [dev_pixelpipe] took 0,007 secs (0,003 CPU) [preview] processed `channelmixerrgb' on GPU, blended on GPU
34307,9576 [dev_pixelpipe] took 0,371 secs (0,356 CPU) [preview] processed `diffuse' on GPU, blended on GPU
35307,9613 [dev_pixelpipe] took 0,003 secs (0,002 CPU) [preview] processed `colorbalancergb' on GPU, blended on GPU
36307,9659 [dev_pixelpipe] took 0,005 secs (0,000 CPU) [preview] processed `filmicrgb' on GPU, blended on GPU
37307,9686 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,002 secs (0,000 GPU) [colorout]
38307,9847 [dev_pixelpipe] took 0,019 secs (0,008 CPU) [preview] processed `colorout' on GPU, blended on GPU
39308,0043 [dev_pixelpipe] took 0,020 secs (0,011 CPU) [preview] processed `dither' on CPU, blended on CPU
40308,0103 [dev_pixelpipe] took 0,006 secs (0,023 CPU) [preview] processed `gamma' on CPU, blended on CPU
41308,0244 [dt_ioppr_transform_image_colorspace_rgb] `Système' -> `sRVB' took 0,014 secs (0,081 CPU) [final histogram]
42308,0353 [dev_process_image] pixel pipeline took 0,553 secs (0,604 CPU) processing `2022-06-17__DSC00078.arw'

Nogmaals, de cache van Ansel werkt gewoon: het uitschakelen van diffuse or sharpen leidt ertoe dat alleen de verderop gelegen modules opnieuw worden berekend, wat 172 ms duurt. Nogmaals, de cache van Darktable werkt niet, wat leidt tot het opnieuw berekenen van de volledige 2 pipelines (voorbeeld en hoofd), voor een totale kost van 6,9 s. Dat is een prestatieverlies van ×40, mensen! Dat maakt alle valse versnellingen van +15 % van Ralf Brown compleet irrelevant! Maar hé! Blijf je verloren sleutels zoeken waar je je voeten kunt zien in plaats van waar je ze verloren bent! .

Een kleur prikken in een module

We stellen de witbalans in color calibration in met de kleurenprikker, op het zoomniveau “zoom to fit”.

 1colorpicker stats reading took 0.020 secs (0.088 CPU)
 2colorpicker stats reading took 0.018 secs (0.087 CPU)
 312.128030 [dev_pixelpipe] pipeline resync with history took 0.024 secs (0.037 CPU) for pipe virtual-preview
 412.137829 [dev_pixelpipe] pipeline resync with history took 0.024 secs (0.056 CPU) for pipe preview
 512.157665 [dev_pixelpipe] took 0.020 secs (0.048 CPU) processed `color calibration' on GPU, blended on GPU [preview]
 613.327326 [dev_pixelpipe] took 1.170 secs (1.231 CPU) processed `diffuse or sharpen' on GPU, blended on GPU [preview]
 713.336618 [dev_pixelpipe] took 0.009 secs (0.008 CPU) processed `color balance rgb' on GPU, recycled cacheline, blended on GPU [preview]
 813.345393 [dev_pixelpipe] took 0.009 secs (0.007 CPU) processed `filmic rgb' on GPU, recycled cacheline, blended on GPU [preview]
 913.368053 [dev_pixelpipe] took 0.023 secs (0.030 CPU) processed `output color profile' on GPU, blended on  [preview]
1013.418643 [dev_pixelpipe] took 0.050 secs (0.061 CPU) processed `dithering' on CPU, blended on  [preview]
1113.435846 [dev_pixelpipe] took 0.017 secs (0.024 CPU) processed `display encoding' on GPU, blended on  [preview]
1213.435919 [pixelpipe] preview internal pixel pipeline processing took 1.298 secs (1.408 CPU)
1313.435949 [dev_process_preview] pipeline processing thread took 1.298 secs (1.408 CPU)
1413.526316 [dev_pixelpipe] pipeline resync with history took 0.080 secs (0.376 CPU) for pipe full
1513.526443 [dev_process_full] pipeline processing thread took 0.000 secs (0.000 CPU)
16colorpicker stats reading took 0.185 secs (0.741 CPU)
17image colorspace transform RGB-->RGB took 0.000 secs (0.000 CPU) [[histogram] sample swatch]
18image colorspace transform RGB-->RGB took 0.000 secs (0.000 CPU) [[histogram] sample swatch]
19image colorspace transform RGB-->RGB took 0.000 secs (0.000 CPU) [[histogram] sample swatch]
 116,1190 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
 216,1364 dt_color_picker_helper stats reading 4 channels (filters 2492765332) cst 2 -> 2 size 1118880 denoised 0 took 0,001 secs (0,005 CPU)
 316,1396 [dev_pixelpipe] took 0,020 secs (0,025 CPU) [preview] processed `channelmixerrgb' on GPU, blended on GPU
 416,2071 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
 516,6064 [dev_pixelpipe] took 0,467 secs (0,567 CPU) [preview] processed `diffuse' on GPU, blended on GPU
 616,6106 [dev_pixelpipe] took 0,004 secs (0,004 CPU) [preview] processed `colorbalancergb' on GPU, blended on GPU
 716,6160 [dev_pixelpipe] took 0,005 secs (0,001 CPU) [preview] processed `filmicrgb' on GPU, blended on GPU
 816,6192 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,003 secs (0,002 GPU) [colorout]
 916,6364 [dev_pixelpipe] took 0,020 secs (0,010 CPU) [preview] processed `colorout' on GPU, blended on GPU
1016,6513 [dev_pixelpipe] took 0,015 secs (0,005 CPU) [preview] processed `dither' on CPU, blended on CPU
1116,6572 [dev_pixelpipe] took 0,006 secs (0,023 CPU) [preview] processed `gamma' on CPU, blended on CPU
1216,6584 dt_color_picker_helper stats reading 4 channels (filters 2492765332) cst 2 -> 2 size 1118880 denoised 0 took 0,001 secs (0,005 CPU)
1316,6586 [dt_ioppr_transform_image_colorspace] IOP_CS_RGB-->IOP_CS_LAB took 0,000 secs (0,000 CPU) [gamma]
1416,6587 [dt_ioppr_transform_image_colorspace_rgb] `Système' -> `sRVB' took 0,000 secs (0,000 CPU) [primary picker]
1516,6754 [dt_ioppr_transform_image_colorspace_rgb] `Système' -> `sRVB' took 0,017 secs (0,063 CPU) [final histogram]
1616,6843 [histogram] took 0,026 secs (0,093 CPU) final waveform
1716,6847 [dev_process_image] pixel pipeline took 0,566 secs (0,733 CPU) processing `2022-06-17__DSC00078.arw'
18
1916,6854 [dt_dev_process_image_job] loading image. took 0,000 secs (0,000 CPU)
2020,3395 [dev_pixelpipe] took 3,606 secs (3,778 CPU) [full] processed `highlights' on GPU with tiling, blended on CPU
2120,7350 [resample_cl] plan 0,001 secs (0,000 CPU) resample 0,010 secs (0,001 CPU)
2220,8263 [dev_pixelpipe] took 0,487 secs (0,285 CPU) [full] processed `demosaic' on GPU, blended on GPU
2320,8389 [dev_pixelpipe] took 0,012 secs (0,002 CPU) [full] processed `lens' on GPU, blended on GPU
2420,8505 [dev_pixelpipe] took 0,012 secs (0,002 CPU) [full] processed `exposure' on GPU, blended on GPU
2520,8812 [dev_pixelpipe] took 0,031 secs (0,008 CPU) [full] processed `colorin' on GPU, blended on GPU
2620,8972 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,016 secs (0,004 GPU) [channelmixerrgb]
2720,9551 [dev_pixelpipe] took 0,074 secs (0,023 CPU) [full] processed `channelmixerrgb' on GPU, blended on GPU
2821,8137 [dev_pixelpipe] took 0,000 secs (0,000 CPU) initing base buffer [preview]
2921,8160 [dev_pixelpipe] took 0,001 secs (0,005 CPU) [preview] processed `rawprepare' on CPU, blended on CPU
3021,8173 [dev_pixelpipe] took 0,001 secs (0,001 CPU) [preview] processed `temperature' on CPU, blended on CPU
3121,9879 [dev_pixelpipe] took 0,171 secs (0,758 CPU) [preview] processed `highlights' on CPU, blended on CPU
3222,0020 [dev_pixelpipe] took 0,014 secs (0,080 CPU) [preview] processed `demosaic' on CPU, blended on CPU
3322,0103 [dev_pixelpipe] took 0,008 secs (0,016 CPU) [preview] processed `lens' on CPU, blended on CPU
3422,0127 [dev_pixelpipe] took 0,002 secs (0,014 CPU) [preview] processed `exposure' on CPU, blended on CPU
3522,0155 [dev_pixelpipe] took 0,003 secs (0,015 CPU) [preview] processed `colorin' on CPU, blended on CPU
3622,0172 [dt_ioppr_transform_image_colorspace] IOP_CS_LAB-->IOP_CS_RGB took 0,002 secs (0,009 CPU) [channelmixerrgb]
3722,0457 dt_color_picker_helper stats reading 4 channels (filters 2492765332) cst 2 -> 2 size 1118880 denoised 0 took 0,002 secs (0,013 CPU)
3822,0458 [dev_pixelpipe] took 0,030 secs (0,180 CPU) [preview] processed `channelmixerrgb' on CPU, blended on CPU
3922,6461 [dev_pixelpipe] took 1,691 secs (5,549 CPU) [full] processed `diffuse' on GPU, blended on GPU
4022,6595 [dev_pixelpipe] took 0,013 secs (0,079 CPU) [full] processed `colorbalancergb' on GPU, blended on GPU
4122,6725 [dev_pixelpipe] took 0,013 secs (0,073 CPU) [full] processed `filmicrgb' on GPU, blended on GPU
4222,6824 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,007 secs (0,041 GPU) [colorout]
4322,7443 [dev_pixelpipe] took 0,072 secs (0,398 CPU) [full] processed `colorout' on GPU, blended on GPU
4422,8624 [dev_pixelpipe] took 0,118 secs (0,664 CPU) [full] processed `dither' on CPU, blended on CPU
4522,8878 [dev_pixelpipe] took 0,025 secs (0,172 CPU) [full] processed `gamma' on CPU, blended on CPU
4622,8894 [dev_process_image] pixel pipeline took 6,637 secs (11,596 CPU) processing `2022-06-17__DSC00078.arw'
4723,4204 [dev_pixelpipe] took 1,374 secs (8,556 CPU) [preview] processed `diffuse' on CPU, blended on CPU
4823,5271 [dev_pixelpipe] took 0,106 secs (0,617 CPU) [preview] processed `colorbalancergb' on CPU, blended on CPU
4923,5788 [dev_pixelpipe] took 0,051 secs (0,291 CPU) [preview] processed `filmicrgb' on CPU, blended on CPU
5023,5817 [dt_ioppr_transform_image_colorspace] IOP_CS_RGB-->IOP_CS_LAB took 0,003 secs (0,011 CPU) [colorout]
5123,5870 [dev_pixelpipe] took 0,008 secs (0,037 CPU) [preview] processed `colorout' on CPU, blended on CPU
5223,5913 [dev_pixelpipe] took 0,004 secs (0,004 CPU) [preview] processed `dither' on CPU, blended on CPU
5323,5964 [dev_pixelpipe] took 0,005 secs (0,021 CPU) [preview] processed `gamma' on CPU, blended on CPU
5423,5973 dt_color_picker_helper stats reading 4 channels (filters 2492765332) cst 2 -> 2 size 1118880 denoised 0 took 0,001 secs (0,006 CPU)
5523,5976 [dt_ioppr_transform_image_colorspace] IOP_CS_RGB-->IOP_CS_LAB took 0,000 secs (0,000 CPU) [gamma]
5623,5977 [dt_ioppr_transform_image_colorspace_rgb] `Système' -> `sRVB' took 0,000 secs (0,000 CPU) [primary picker]
5723,6099 [dt_ioppr_transform_image_colorspace_rgb] `Système' -> `sRVB' took 0,012 secs (0,067 CPU) [final histogram]
5823,6215 [histogram] took 0,024 secs (0,097 CPU) final waveform
5923,6219 [dev_process_image] pixel pipeline took 6,889 secs (15,651 CPU) processing `2022-06-17__DSC00078.arw'

Ansel hoeft geen nieuwe pipeline-rendering te starten om de kleurenprikker te bemonsteren omdat de invoer en uitvoer van de module nog steeds in de cache zitten, dus het duurt in totaal 40 ms om te bemonsteren. Vervolgens worden de nieuwe parameters vastgelegd in de module, wat de geschiedenis wijzigt en een herberekening van de module color calibration en alle verderop gelegen modules activeert. Totale bestede tijd: 1,4 s.

Darktable moet een nieuwe pipeline-rendering herstarten om de kleurenprikker te bemonsteren, want waarom niet? Dat duurt 0,6 s. Het zal je verheugen te vernemen dat Darktable kleur op de GPU bemonstert, wat slechts 1 ms duurt (midden in die 0,6 s pipelineruntime), terwijl Ansel op de CPU bemonstert in 20 ms. Vervolgens worden de parameters van de kleurenprikker vastgelegd in de geschiedenis, wat een volledige herberekening van de 2 pipelines herstart. Totale bestede tijd: 7,5 s.

Dat is een prestatieverlies van ×5,4 voor Darktable, en dat allemaal omdat ze hun pipelines niet verbeteren maar elke mogelijke dwaze speurtocht ondernemen die er is.

Exporteren op volledige resolutie

We exporteren nadat we de afbeelding in de donkere kamer hebben geopend. Dit is belangrijk. De “high quality”-bemonstering wordt gebruikt in Darktable, in Ansel is het de enige modus.

 118.917740 [dev_pixelpipe] took 0.000 secs (0.000 CPU) to load the image.
 218.970877 [export] creating pixelpipe took 0.054 secs (0.074 CPU)
 319.215438 [dev_pixelpipe] took 0.244 secs (0.222 CPU) processed `exposure' on GPU, blended on GPU [export]
 419.241544 [dev_pixelpipe] took 0.026 secs (0.025 CPU) processed `input color profile' on GPU, blended on  [export]
 519.267887 [dev_pixelpipe] took 0.026 secs (0.026 CPU) processed `color calibration' on GPU, blended on GPU [export]
 656.171662 [dev_pixelpipe] took 36.904 secs (36.592 CPU) processed `diffuse or sharpen' on GPU with tiling, blended on CPU [export]
 756.364588 [dev_pixelpipe] took 0.193 secs (0.156 CPU) processed `color balance rgb' on GPU, blended on GPU [export]
 857.293819 [dev_pixelpipe] took 0.929 secs (0.468 CPU) processed `filmic rgb' on GPU with tiling, blended on CPU [export]
 957.516252 [dev_pixelpipe] took 0.222 secs (0.176 CPU) processed `output color profile' on GPU, blended on  [export]
1057.534628 [dev_pixelpipe] took 0.018 secs (0.017 CPU) processed `Final resampling' on GPU, blended on  [export]
1158.462789 [dev_pixelpipe] took 0.928 secs (0.544 CPU) processed `dithering' on CPU, blended on  [export]
1258.462829 [pixelpipe] export internal pixel pipeline processing took 39.492 secs (38.227 CPU)
1358.462898 [dev_process_export] pixel pipeline processing thread took 39.492 secs (38.227 CPU)
14[export_job] exported to `/home/aurelienpierre/Téléchargements/2022-06-17__DSC00078_08.jpg'
 1526,9861 [export] creating pixelpipe took 0,063 secs (0,091 CPU)
 2526,9862 [dev_pixelpipe] took 0,000 secs (0,000 CPU) initing base buffer [export]
 3527,0072 [dev_pixelpipe] took 0,021 secs (0,020 CPU) [export] processed `rawprepare' on GPU, blended on GPU
 4527,0237 [dev_pixelpipe] took 0,016 secs (0,007 CPU) [export] processed `temperature' on GPU, blended on GPU
 5530,7560 [dev_pixelpipe] took 3,732 secs (3,868 CPU) [export] processed `highlights' on GPU with tiling, blended on CPU
 6531,1444 [dev_pixelpipe] took 0,388 secs (0,201 CPU) [export] processed `demosaic' on GPU, blended on GPU
 7531,9899 [dev_pixelpipe] took 0,845 secs (0,493 CPU) [export] processed `lens' on GPU with tiling, blended on CPU
 8532,1378 [dev_pixelpipe] took 0,148 secs (0,139 CPU) [export] processed `exposure' on GPU, blended on GPU
 9532,1968 [dev_pixelpipe] took 0,059 secs (0,047 CPU) [export] processed `colorin' on GPU, blended on GPU
10532,2287 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,031 secs (0,019 GPU) [channelmixerrgb]
11532,3206 [dev_pixelpipe] took 0,124 secs (0,089 CPU) [export] processed `channelmixerrgb' on GPU, blended on GPU
12575,5645 [dev_pixelpipe] took 43,244 secs (43,220 CPU) [export] processed `diffuse' on GPU with tiling, blended on CPU
13575,7422 [dev_pixelpipe] took 0,178 secs (0,167 CPU) [export] processed `colorbalancergb' on GPU, blended on GPU
14576,2975 [dev_pixelpipe] took 0,555 secs (0,474 CPU) [export] processed `filmicrgb' on GPU with tiling, blended on CPU
15576,3897 [resample_cl] took 0,000 secs (0,000 CPU) 1:1 copy/crop of 7968x5320 pixels
16576,4081 [dev_pixelpipe] took 0,111 secs (0,101 CPU) [export] processed `finalscale' on GPU, blended on GPU
17576,4403 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,032 secs (0,020 GPU) [colorout]
18576,5618 [dev_pixelpipe] took 0,154 secs (0,120 CPU) [export] processed `colorout' on GPU, blended on GPU
19577,0202 [dev_pixelpipe] took 0,458 secs (0,456 CPU) [export] processed `dither' on CPU, blended on CPU
20577,0204 [dev_process_export] pixel pipeline processing took 50,034 secs (49,403 CPU)
21578,2407 [export_job] exported to `/home/aurelienpierre/Téléchargements/2022-06-17__DSC00078_06.jpg'

In Ansel, aangezien we de afbeelding eerder in de donkere kamer hebben geopend, zitten de vroege stadia van de pipeline nog steeds in de cache, dus de export begint bij de module exposure en duurt 39,5 s. In Darktable, tja… business as usual: het is een volledige herberekening van de pipeline die 50 s duurt.

Opnieuw exporteren op halve resolutie

We exporteren op halve resolutie meteen na het exporteren op volledige resolutie.

165.601240 [dev_pixelpipe] took 0.000 secs (0.000 CPU) to load the image.
265.658874 [export] creating pixelpipe took 0.060 secs (0.079 CPU)
365.912677 [dev_pixelpipe] took 0.254 secs (0.233 CPU) processed `output color profile' on GPU, blended on  [export]
465.972780 [dev_pixelpipe] took 0.060 secs (0.073 CPU) processed `Final resampling' on GPU, blended on  [export]
566.160165 [dev_pixelpipe] took 0.187 secs (0.238 CPU) processed `dithering' on CPU, blended on  [export]
666.160184 [pixelpipe] export internal pixel pipeline processing took 0.501 secs (0.544 CPU)
766.160202 [dev_process_export] pixel pipeline processing thread took 0.501 secs (0.545 CPU)
8[export_job] exported to `/home/aurelienpierre/Téléchargements/2022-06-17__DSC00078_09.jpg'
 1607,7584 [export] creating pixelpipe took 0,064 secs (0,088 CPU)
 2607,7586 [dev_pixelpipe] took 0,000 secs (0,000 CPU) initing base buffer [export]
 3607,7918 [dev_pixelpipe] took 0,033 secs (0,028 CPU) [export] processed `rawprepare' on GPU, blended on GPU
 4607,8083 [dev_pixelpipe] took 0,016 secs (0,007 CPU) [export] processed `temperature' on GPU, blended on GPU
 5611,5555 [dev_pixelpipe] took 3,747 secs (3,865 CPU) [export] processed `highlights' on GPU with tiling, blended on CPU
 6611,9454 [dev_pixelpipe] took 0,390 secs (0,201 CPU) [export] processed `demosaic' on GPU, blended on GPU
 7612,7083 [dev_pixelpipe] took 0,763 secs (0,462 CPU) [export] processed `lens' on GPU with tiling, blended on CPU
 8612,8559 [dev_pixelpipe] took 0,148 secs (0,137 CPU) [export] processed `exposure' on GPU, blended on GPU
 9612,9149 [dev_pixelpipe] took 0,059 secs (0,045 CPU) [export] processed `colorin' on GPU, blended on GPU
10612,9468 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_LAB-->IOP_CS_RGB took 0,032 secs (0,021 GPU) [channelmixerrgb]
11613,0390 [dev_pixelpipe] took 0,124 secs (0,090 CPU) [export] processed `channelmixerrgb' on GPU, blended on GPU
12656,1897 [dev_pixelpipe] took 43,151 secs (42,852 CPU) [export] processed `diffuse' on GPU with tiling, blended on CPU
13656,3673 [dev_pixelpipe] took 0,178 secs (0,167 CPU) [export] processed `colorbalancergb' on GPU, blended on GPU
14656,9163 [dev_pixelpipe] took 0,549 secs (0,467 CPU) [export] processed `filmicrgb' on GPU with tiling, blended on CPU
15657,0078 [resample_cl] plan 0,001 secs (0,000 CPU) resample 0,001 secs (0,000 CPU)
16657,1070 [dev_pixelpipe] took 0,191 secs (0,181 CPU) [export] processed `finalscale' on GPU, blended on GPU
17657,1233 [dt_ioppr_transform_image_colorspace_cl] IOP_CS_RGB-->IOP_CS_LAB took 0,016 secs (0,004 GPU) [colorout]
18657,1792 [dev_pixelpipe] took 0,072 secs (0,030 CPU) [export] processed `colorout' on GPU, blended on GPU
19657,3186 [dev_pixelpipe] took 0,139 secs (0,136 CPU) [export] processed `dither' on CPU, blended on CPU
20657,3187 [dev_process_export] pixel pipeline processing took 49,560 secs (48,669 CPU)
21657,8107 [export_job] exported to `/home/aurelienpierre/Téléchargements/2022-06-17__DSC00078_07.jpg'

Omdat Ansel altijd op volledige resolutie exporteert tot aan de module Final resampling (de modus die in Darktable “high quality” heet), blijft de pipeline grotendeels hetzelfde ongeacht de uiteindelijke grootte. Aangezien de cache van Ansel werkt, zit de eerder geëxporteerde afbeelding op volledige resolutie nog steeds in de cache, dus we herberekenen alleen de laatste stadia: output color profile, downsampling, dithering. Dat duurt 0,5 s.

Darktable beheert, zoals gewoonlijk, niet wat het eerder heeft berekend, dus je zit vast aan nog een volledige export van ~50 s. Oftewel een prestatieverlies van ×100.

Merk op dat de pipelinecache van Ansel een garbage collection heeft die alle ongebruikte cacheregels ouder dan 5 minuten leegmaakt, dus dit zou niet werken als je te lang wacht.

Conclusie

Het is hilarisch om te lezen, op tech-bro-forums zoals discuss.pixls.us , dat mensen Darktable meer vertrouwen dan Ansel omdat de eerste veel meer aapjes heeft die met hun handen in de lucht zwaaien en doen alsof ze werken, wat blijkbaar genoeg is om een compleet verkeerd gevoel van betrouwbaarheid en vertrouwen te geven. Het is gewoon het ultieme bewijs dat mensen geen idee hebben wat er in de code gebeurt. Maar het is een kapitalistische ziekte om agitatie te verwarren met werk, en werk dat geen waarde creëert kan nog steeds als vooruitgang verkocht worden met de juiste marketing.

Ik doe niet aan meningen, ik doe aan benchmarks. De cijfers die ik hier heb gepubliceerd kunnen volledig gereproduceerd worden:

Darktable performance penalty per benchmark case
  • individuele modules zijn gemiddeld 1,4 keer sneller op Ansel CPU vergeleken met Darktable CPU,
  • individuele modules zijn gemiddeld 1,6 keer sneller op Ansel GPU vergeleken met Darktable GPU,
  • volledige pipelines zijn ergens tussen 1,5 keer en 100 keer sneller op Ansel vergeleken met Darktable GPU, omdat Ansel een werkende cache heeft,
  • Ansel is niet alleen sneller, het is ook energiezuiniger, omdat er minder dingen (her)berekend worden.

Dit alles werd bereikt door GUI-code uit de pipeline-renderingcode te verwijderen, door de levenscyclus van de gegevens duidelijker, eenvoudiger en robuuster te maken, niet door meer afhandeling van speciale gevallen en tijdelijke oplossingen toe te voegen. Ansel kan veel meer RAM gebruiken dan Darktable, terwijl het de boekhouding doet die nodig is om te weten hoeveel het daadwerkelijk gebruikt en of het geheugen moet gaan hergebruiken.

Dit alles is het bewijs dat het Darktable-“team” de software niet beter maakt, dat zijn (gebrek aan) management de software actief schaadt. Er zijn sinds 2022 veel “optimalisaties” aangekondigd in de versienotities. En toch is hun software nog steeds een pijnlijk traag beest van inefficiëntie.

Merk op dat de per-module-optimalisaties die in Darktable zijn gedaan kunnen worden overgezet naar Ansel, hoewel ze niet allemaal daadwerkelijke versnellingen lijken te zijn op basis van wat hier wordt getoond. Sommige zijn al overgezet. Maar Darktable kan de pipeline-architectuur van Ansel niet overzetten, en daar komen de meeste van onze versnellingen vandaan.

Tijdens dit werk verloor ik ook mijn vertrouwen in Vkdt . Vkdt is een hernieuwde poging, van de oprichter van Darktable, Johannes Hannika, om een RAW-fotosoftware helemaal opnieuw op te bouwen en volledig op de GPU te draaien via Vulkan. Maar na 4 jaar de troep van andere mensen op te ruimen, zijn er een paar dingen die ik heb geleerd:

  1. De vertragingen van Darktable zijn niet te wijten aan de GTK-stack of de OpenCL-stack. Toegegeven, die zijn niet geweldig, maar dat is beheersbaar. Het zijn programmeerfouten en slecht ontwerp dat niet opnieuw werd geëvalueerd toen de behoeften en eisen van de software veranderden.
  2. Een cache-eerst-ontwerp maakt het mogelijk om veel latenties te verbergen door herberekeningen te vermijden, en een volledig-GPU-workflow zal binnenkort de geheugenbeperkingen van GPU’s tegenkomen.
  3. GPU’s worden steeds duurder, na de hausse van cryptovaluta en nu de hausse van AI.
  4. Wat Darktable heeft gedood was een gebrek aan management en een gebrek aan visie, een cultuur van “laissez faire” en vrolijke willekeur, die alleen werkt met een handvol ontwikkelaars die elkaar allemaal kennen. Vkdt gaat dezelfde kant op. Als code en functies mogen groeien zonder prioriteiten en aanscherping van de API, is het een crashende trein in slow motion. “nieuwer = beter” is slechts een tijdelijke toestand. De echte uitdaging is het beheersen van groei.

Vanuit het perspectief van een ontwikkelaar heeft Darktable 3 belangrijke ziekten:

  1. Zijn ontwikkelaars missen volledig (en al lange tijd) de abstractievaardigheden om cognitief te scheiden wat tot de GUI-laag behoort en wat tot de backend-laag. Als gevolg daarvan vind je GUI/GTK-toestanden diep verankerd in backend-lagen, wat des te vervelender is gezien darktable-cli headless draait en beide modi dwingt beheerd te worden. Maar je vindt ook herhaaldelijk GUI-problemen opgelost in de backend-laag, en andersom. Die veroorzaken echte betrouwbaarheidsproblemen, bovenop het feit dat ze het geheel ingewikkeld, onleesbaar en verstrengeld maken.
  2. Zijn ontwikkelaars begrijpen het concept van privé-API’s en inkapseling niet: alle datastructuren zijn openbaar, alle headerbestanden worden door de hele software geïmporteerd, dus de hele software weet van de hele software en mag datastructuren ter plekke wijzigen vanaf elke plek in de code.
  3. Complexiteit wordt “opgelost” met meer complexiteit, en niemand lijkt dat te zien als een probleem genaamd technische schuld.

Gezonde codebases beschermen gegevens door ze privé te maken en interacties te dwingen via getter/setter-functies die als openbare API’s zijn gedefinieerd. Dit maakt eenvoudig beheer van threadveiligheid mogelijk wanneer de tijd daar is, maar stelt ons ook in staat om vanaf een centrale plek bij te houden wat waar en wanneer schrijft. En vervolgens neem je de minimale set API’s in elk bestand op, om code zoveel mogelijk te isoleren.

In plaats daarvan schrijft de broncode van Darktable overal vandaan naar overal, zonder goede interfaces. Dus elke soort wijziging in de codebase van Darktable veroorzaakt systematisch randeffecten en breekt iets onverwachts aan de andere kant van de software, in deprimerende sessies van mollenmeppen die voortkomen uit luiheid en domheid.

Er is dus veel vervelend werk in Ansel gedaan om API’s aan te scherpen, zoveel mogelijk datastructuren te privatiseren, en bibliotheken van elkaar te isoleren om de afhankelijkheidsgrafiek enigszins te ontwarren.

Bijlage: de plannen

Volledige architectuur

Hier is het high-level stroomschema van de hele architectuur, van database tot backbuffers. Nu kunnen we eindelijk een stroomschema van deze puinhoop tekenen.

flowchart TD
  subgraph Module
    M["Module instance
dt_iop_module_t"] end subgraph Develop H["dev->history
history items"] D["dt_develop_t
history_end
history_hash"] end subgraph Persist["DB + image cache"] DB["SQLite history tables"] IC["image cache
dt_image_t"] end subgraph Pipeline F["Pipe dirty flags"] P["Pipe nodes / pieces"] G["global_hash"] B["Backbuf"] end subgraph Cache C["Pixelpipe cache"] end subgraph Consumers["Backbuffer consumers"] DR["darkroom.c"] NAV["navigation.c"] EXP["imageio.c"] end M -->|"write snapshot
dt_dev_add_history_item_real()"| H H -->|"update history_end / history_hash
dt_dev_add_history_item_real()"| D D -->|"write history
dt_dev_write_history_ext()"| DB D -->|"write image-side hash
dt_dev_write_history_ext()"| IC DB -.->|"read history
dt_dev_read_history_ext()"| H IC -.->|"read image metadata
dt_dev_read_history_ext()"| H H -->|"apply to modules
dt_dev_pop_history_items_ext()"| M D -->|"mark pipes dirty
dt_dev_add_history_item_real()"| F D -->|"check history mismatch
dt_dev_darkroom_pipeline()"| F H -->|"sync history into pipe
dt_dev_pixelpipe_change()"| P F -->|"consume dirty flags
dt_dev_pixelpipe_change()"| P P -->|"compute cache keys
dt_pixelpipe_get_global_hash()"| G G -->|"key cache entries
dt_dev_pixelpipe_process_rec()"| C C -.->|"read exact-hit / input
dt_dev_pixelpipe_process_rec()"| P P -->|"publish stage output
dt_dev_pixelpipe_process_rec()"| C C -->|"promote final output
dt_dev_pixelpipe_process()"| B B -->|"borrow main/preview backbuf
_darkroom_expose()"| DR B -->|"copy preview backbuf
_lib_navigation_draw_callback()"| NAV B -->|"borrow export backbuf
dt_imageio_export_with_flags()"| EXP EXP -->|"update mipmap hash
dt_imageio_export_with_flags()"| IC

RAM/vRAM-geheugenbeheer

Beheer van cachebuffers:

flowchart TD
  H["CPU RAM buffer"]
  P["Pinned vRAM buffer
CL_MEM_USE_HOST_PTR"] V["Device-only vRAM buffer"] G["pixelpipe_process_on_GPU()"] C["pixelpipe_process_on_CPU()"] H -->|"prepare GPU input
dt_dev_pixelpipe_cache_prepare_cl_input()"| P P -->|"sync host/device if needed
dt_dev_pixelpipe_cache_sync_cl_buffer()"| G V -->|"reuse existing vRAM input
dt_dev_pixelpipe_cache_prepare_cl_input()"| G G -->|"publish pinned output
dt_dev_pixelpipe_cache_release_cl_buffer()"| P G -->|"publish device-only output
dt_dev_pixelpipe_cache_release_cl_buffer()"| V V -->|"GPU to CPU fallback copy
dt_dev_pixelpipe_cache_restore_cl_buffer()"| H H -->|"resume CPU processing
pixelpipe_process_on_CPU()"| C

Als de uitvoer van de module gepland is voor caching (vanwege gebruikersvoorkeur, behoefte aan deze buffer voor histogram/kleurenprikker, of de volgende module is degene die actief is in de GUI), gebruikt OpenCL een vastgezette geheugenbuffer (vastgezet op de RAM-cache). We zetten ook invoergeheugenbuffers vast, wanneer de GPU invoer neemt uit de RAM-cache. Dit is iets duurder dan het gebruik van een pure device-only buffer, maar minder duur dan het kopiëren van die device-only buffer naar de host. Als de OpenCL-uitvoer niet gepland is voor caching, gebruiken we een device-only buffer die later hergebruikt kan worden maar nooit naar RAM wordt gekopieerd.

In geval van een OpenCL-fout voor een bepaalde module (de meest voor de hand liggende: onvoldoende geheugen), wordt de GPU-invoerbuffer transparant terug naar de RAM-cache gekopieerd voordat wordt teruggevallen op het pure-CPU-pad.

Al die buffers worden bijgehouden door cache-items, die een RAM-buffer koppelen aan een vRAM-buffer (als we beide gebruiken in een vastgezette situatie), of gewoon bijhouden wat er is toegewezen. Als een GPU-geheugentoewijzing mislukt, doorzoeken we eerst de cache om alle eerder toegewezen buffers vrij te geven. Als de GPU-geheugentoewijzing daarna opnieuw mislukt, vallen we terug op de CPU.

Cache-items

De cache is een hashtabel van cache-items. Hun sleutel is een hash/checksum. We hebben 2 soorten cache-items:

  • interne, gebruikt als herbruikbare buffers voor invoer/uitvoer van modules,
  • externe, gebruikt als wegwerpbuffers voor tussenliggende berekeningen van modules.

Interne cache-items zijn gesleuteld op de global_hash van hun bovenliggende module, en kunnen later weer worden teruggevonden (zelfs vanuit de GUI) omdat die hash stabiel is over runs en pipelines heen. Ze kunnen opnieuw gesleuteld worden als we hun geheugenbuffer hergebruiken, zodat de nieuwe sleutel overeenkomt met de nieuwe toestand van hun bovenliggende module. Die cache-items kunnen vergrendeld worden in lees- of schrijfmodus voor veilige gelijktijdige toegang tussen parallelle threads. Een schrijfvergrendeling kan door slechts één thread worden vastgelegd als geen enkele andere thread aan het lezen is, een leesvergrendeling kan door meerdere threads worden vastgelegd als geen enkele andere thread aan het schrijven is. Aangezien de schrijfvergrendeling wordt vrijgegeven door de module die zijn uitvoer schrijft eerder dan de leesvergrendeling wordt verkregen door de module die hetzelfde cache-item als invoer gebruikt, en er in de tussentijd een risico op verwijdering bestaat, hebben ze ook een refcount-mechanisme: de producent van het cache-item verhoogt het, de consument verlaagt het. Hetzelfde mechanisme wordt door de donkere kamer gebruikt om de backbuffer op te halen zonder kopie.

Externe cache-items zijn gesleuteld op het geheugenadres van hun databuffer. Ze worden verondersteld kortstondig te zijn.

Het toevoegen/verwijderen van cache-items verhoogt/verlaagt automatisch de globale cachegrootte. We blijven nieuwe items toevoegen zolang de globale cachegrootte onder de toegestane drempel ligt, waarna we de oudste items beginnen te vernietigen als hun refcount 0 is en ze niet vergrendeld zijn.

flowchart TD
  A["absent"]
  B["reserved for write
refcount + 1
write-locked"] C["published
exact-hit eligible"] D["borrowed by consumer
refcount > 0"] E["backbuf-held
one display ref kept"] F["auto-destroy flagged"] G["removed / freed"] A -->|"create new entry
dt_dev_pixelpipe_cache_get()
dt_dev_pixelpipe_cache_get_writable()"| B C -->|"rekey reusable entry
dt_dev_pixelpipe_cache_get_writable()
dt_dev_pixelpipe_cache_rekey()"| B B -->|"backend finishes and unlocks
dt_dev_pixelpipe_process_rec()"| C C -->|"exact-hit / reopen / GUI read-only
dt_dev_pixelpipe_cache_peek()
dt_dev_pixelpipe_cache_get_read_only()"| D D -->|"release consumer ref
dt_dev_pixelpipe_cache_unref_hash()
dt_dev_pixelpipe_cache_close_read_only()"| C C -->|"keep final output alive for display
_update_backbuf_cache_reference()"| E E -->|"backbuf changes or invalidates
_update_backbuf_cache_reference()"| C C -->|"mark transient output
dt_dev_pixelpipe_cache_flag_auto_destroy()"| F F -->|"reap when no ref and no lock remain
dt_dev_pixelpipe_cache_auto_destroy_apply()"| G C -->|"explicit remove / GC / LRU
dt_dev_pixelpipe_cache_remove()
dt_dev_pixelpipe_cache_flush_old()
dt_dev_pixel_pipe_cache_remove_lru()"| G C -->|"invalid payload detected
dt_dev_pixelpipe_cache_peek()"| G

Een cache-item weet niet wat voor soort gegevens het bevat. Het kent alleen de adressen van de buffers, hun grootte, hun refcount en hun vergrendelingstoestand. Het is dus een generieke abstractie van spullen die zich in het geheugen bevinden.


Translated from English by : Claude. In case of conflict, inconsistency or error, the English version shall prevail.