Jelentősen növelné az assembly kódok arányát kódbázisában az FFmpeg

Címkék

Miközben azt látjuk, hogy egy csomó projekt C irányból a "magasabb szintű" Rust felé mozdul, az FFmpeg azt látná üdvözítőnek, ha az alacsonyabb szintű assembly kód aránya nőne kódbázisában. Nemrég arról posztoltak, hogy a kínai Alibaba Group által küldött, kézzel írt assembly kódhozzájárulások akár 14-szer gyorsabbak a C-nél, ezért más vállalatokat is arra biztatnak, hogy kövessék a példát:

A beküldött kódok beolvasztásra is kerülnek:

Később az FFmpeg projekt ismét az assembly-t dicsérte:

Ezután megjegyezték, hogy a céljaik közt szerepel a dav1d AV1 dekóder programnyelv arányának elérése a teljes kódbázisukon:

Majd arról írtak, hogy valóban van min dolgozni, mert jelenleg a kódbázisukban a programnyelvek aránya:

És még a végén egy kapcsolódó retweet is belefért a részükről, jelezve, hogy elkapta őket az asm hév:

Hozzászólások

Hát, ez megint nem a vibe coding, br0 ... 

trey @ gépház

Nem tudom mivel hadakozol, milyen démonjaid vannak, de semmi olyan állítás nem volt, hogy 

  1. überkirály lennék
  2. sok volt a fél év

Olyan állítás volt, hogy az assembly nem vibe coding.

Ahhoz meg nem kell überkirálynak lennem. Megvilágítom neked egy példával:

Ahhoz nem kell matematikusnak lennem, hogy tudjam, nem könnyű deriválni. 

ha komolyan gondolod hogy te majd el tudod donteni, hogy ez most generalt kod-e vagy sem

Ilyen állítás sem volt, kevesebbet kellene munkaidőben italozni/drogozni. 

trey @ gépház

Vagy ahogy Csernyák L. prof mondta anno: "deriválni az elefántot is meg lehet tanítani, de integrálni csak ketten tudnak igazán széles e hazában, az egyik Reiman tanárúr Budapesten, a másikat szerénységem tiltja, hogy megemlítsem."

Szóval ha összeolvassuk a kettőt, azaz akinek nehéz az a deriválás, amit egy elefántnak is meg lehet tanítani, akkor az jön ki, hogy egy tetszőleges elefánt okosabb, mint... :-P

Nekünk Serény azt mondta, leszarja, tudjuk-e a primitívfüggvényeket. ZH-ra tanuljuk meg, egy év múlva meg jó, ha a konstans függvényt kiintegráljuk. Sokkal fontosabb tudni, mit jelent az, amikor mondjuk egy görbe mentén integrálsz a térben. Nem maga az eredmény számít, hanem hogy tudd, mit csinálsz, és miért csinálod.

Egyik kedvenc kérdése volt: Mi a különbség a határozatlan integrál, a primitívfüggvény, és az integrálfüggvény között?
Ezen el szoktak vérezni a csírák. Kiderült hamar, hogy szart se értettek meg.

Fogalmam sincs, hogy mit bohóckodsz, de második mondatoddal elárultad magad, hogy honnan fúj a szél. Nagyon szar már Svájcban migránsként? Jönnél már haza? 

BTW: hallottam itt a HUP-on hírét, hogy hogyan sikerült végigszenvedned az egyetemet, én erre nem verném magam ennyire ...

trey @ gépház

Neked ez a migránsekézés mostanában mániád. Kb. a fél ország már külföldön nyomja, nincs ezen mit csodálkozni. Angliánál még értettem, de Svájccal amúgy mi a bajod?

Azzal meg végképp nem értek egyet, hogy az egyetemmel jöjjön valaki. Senkit nem érdekel. Átment valaki, van diplomája, ha ért valamihez, akkor kb. senki se lesz rá kíváncsi, hogy hányasra volt meg, hány pótvizsgával, hány félév alatt, hogy szenvedte végig. Max. ha ilyen tudományos-kutatói pályára megy valaki, ahol muszáj villogni, hogy évfolyamelső, meg jeles diploma, stb.. Kb. akkora fütyiség, mint régen a vörös diploma volt.

“Linux isn't an OS, it's a troubleshooting sim game.” (a YouTube commenter)

Migránsokkal csak annyi bajom van, hogy állandóan másról sem beszélnek, mint a migránslétükről. Kevesebbet kéne idehordani a problémáitokat, foglalkozni az itteni rendszerrel, amikor nektek is megvan a saját keresztetek ott. 

Egyetem = bizonyítottad, hogy 4 évig be tudtál járni valahova, erre verni? Szerinted ha valakit itt érdekelne az assembly - értsd elég autista lenne hozzá - nem tudná elsajátítani magas szinten? Mi itt a vergődés tárgya? Nem értem.

Azt megértem, ha egy autista programozó, otthon a vasárnapi asztalnál a lakatos apjának, meg a takarítónő anyjának jaszkarizik, hogy de sokra vitte, már számítógépekkel beszélget 3 betűs utasításokkal és ott hasra esnek előtte ... de itt?! :D

trey @ gépház

A migránsok már tapasztalták, hogy mindenütt szar, de legszarabb otthon, ezért nem panaszkodnak. Túlélnek, meg örülnek, hogy lyuk van a valagukon, meg nem kell legalább az Orsós-rendszerrel szívniuk.

Egyetemre végül ugyanazt írod, amit én, így nem is értem mit akartál vele. Természetesen az ASM egy nagyon alacsony szintű, primitív, lineáris, imperatív nyelv, bárki megtanulhatja kézikönyvből, példakódokból, mindenféle egyetem, főiskola nélkül.

Nyilván programozónál inkább lehetne vagizási pont, hogy mennyit keres vagy milyen jelentősebb, ismert, nagyobb projekteket visz, vesz bennük részt, mint hogy milyen nyelven kódol, az kb. a laikusokat, még takarítói szinten se érdekli.

“Linux isn't an OS, it's a troubleshooting sim game.” (a YouTube commenter)

https://r00t.hu/treyblog/20260130/nemet-irigykedes-magyar-allapotok

Tévképzeteid ^ 

Egyetemre végül ugyanazt írod, amit én, így nem is értem mit akartál vele.

Hogy felesleges vergődni vele. 

Természetesen az ASM egy nagyon alacsony szintű, primitív, lineáris, imperatív nyelv, bárki megtanulhatja kézikönyvből, példakódokból, mindenféle egyetem, főiskola nélkül.

Vagyis felesleges vergődni vele. 

Nyilván programozónál inkább lehetne vagizási pont, hogy mennyit keres vagy milyen jelentősebb, ismert, nagyobb projekteket visz, vesz bennük részt,

Óriási vagizási pont, mesélj róla! 

trey @ gépház

Közben egyesek úgy tekintenek a C-re, mint assembly wrapper. Meg azt bizonygatják, hogy nem érdemes assembly-ben bohóckodni, mert a C fordító már nagyon jó.

Ami szerintem igaz is, csak ez eltérő lehet a különböző architektúrákra.
 

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Lokális maximum vs globális maximum. A patch beküldőinek most kellett az optimalizálás tehát megirták assembly-ben. Viszont a helyes irány szerintem az hogy a C fordítót kell felokosjtani hogy az is meg tudja csinálni azokat az optimalizációkat amiket itt láthattunk, mert ezáltal minden C-ben irt, adott architektúrára fordított alkalmazás gyorsulni fog. De ez nyilván messze több idő. 

Ami az esetek nagy részében igaz is. Amikor a fordító C++ állapotgépből kisebb kódot fordít a 8 bites MCU-ra, mint a C-ben megírt bitzsonglőr kód, azért ott érdemes elgondolkodni.
FFmpeg pont egy speciális eset, ahol lehet értelme egyes rutinokat végletekig csiszolni adott architektúrára.

Sok esetben jo a fordito, csak eppen sajnos az is egy bonyolult eszkoz, amit erteni kell. Valamennyire idevago pelda:

std::vector<int> v1 = generate_vector(100);
std::vector<int> v2 = generate_vector(100);
std::vector<int> s(100);

for(auto i=0;i<s.size();++i) {
    s.at(i) = v1.at(i) + v2.at(i);
}

for(auto i=0;i<v.size();++i) {
    s[i] = v1[i] + v2[i];
}

Evekkel ezelott futottunk bele ebbe. Az masodik ciklusnal maga a g++ is be tudta helyettesiteni a megfelelo SSE/Altivec utasitasokat. Az elso verzional nem boldogult vele. Az az ok, hogy mig az elso verzio kivetelt dob, amikor tul/alul indexeli valaki valamelyik tombot, addig a masiknal az indexelesi hiba 'sima' undefined behavior. Tehat az a helyzet allt fenn, hogy az altalaban idiomatikusabbnak tartott c++ kod volt a kevesbe optimalizalhato eset. Fogalmam sincs, hogy ma mi a helyzet, ez a gcc 3 - 4 verzio korul volt (talan inkabb 3.x).

Ez egy tobbe kevesbe klassz dolog a c++ eseteben, mert a nyelven belul tudod kontrollalni, hogy milyen tradeoff-ot csinalsz a teljesitmeny rovasara. Csakhat egy fordito komplex es gyakran nehezen ertheto allat.

Ami szerintem igaz is, csak ez eltérő lehet a különböző architektúrákra.
+1, az ARM optimalizáció a kanyarban sincs az x86-os optimalizációhoz képest, ráadásul nyelvfüggetlen is a java része. Mind a GNU Compiler, mint a Clang egy nyelvfüggetlen közbülső ábrázolást használ az optimalizációs lépés előtt (mondjuk tök másmilyent, de az közös bennük, hogy nyelvfüggetlenek).
Szóval ha teszem azt Ada-ról lenne szó, a GNAT éppúgy bénább ARM-ra optimalizálásban, mint x86-ra, ez nem a C nyelv sajátja, hanem a fordítóé.

Ettől függetlenül egyetértek, semmilyen gépi optimalizáló nem képes meghaladni egy vérprofi programozó kézzel írt Assembly-jének hatékonyságát. Talán majd a kvuantumgépek, de a jelenlegi technológia semmiképp. Ugyanakkor egy átlagos hátulgombolós kopipasztahuszárnál (de pláne egy vibecodernél) már most is jobbak.

Én ezt nagyon jó dolognak tartom, hiszen az egész bolygón mindenki ugyanolyan CPU-t használ.

Nem, de nagyon sok, elsősorban embedded, MCU-ra készülő project van, amelynek nem kell hordozhatónak lennie. Meg lehet ezt úgy is csinálni, hogy ha az adott CPU-ra megvan az assembly, akkor azt fordítjuk, ha nincs, akkor a C-ben írt kódot.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Annyi van meg, hogy minden egyes architekturahoz kell valaki, aki karban is tartja az assembly magiat. Ha a projekt hajlando ezt a koltseget megfizetni, akkor okes. Ellenben, hogy mikor eri meg es mikor nem, az egyedi elbiralas ala esik (nem is feltetlenul technikai ugy).

A veszely annyi, hogyha a platformspecifikus karbantarto nem er ra annyira, hogy mindig vegigverje a valtozasokat a sajat architekturajan, akkor lesz fejvakaras. A kernelben is lattunk ilyeneket, hogy bizonyos platformok tamogatasa azert lett kidobva, mert nincs hozza ember, akinek lenne erre ideje es szakertelme is.

Meg lehet ezt úgy is csinálni, hogy ha az adott CPU-ra megvan az assembly, akkor azt fordítjuk, ha nincs, akkor a C-ben írt kódot.
Úgy van, jól mondod. És nemcsak "lehet", hanem a sebességkritikus függvénykönyvtáraknál ez a bevett gyakorlat (pl. pixman).

És az ffmpeg sem kivétel, az is pont így csinálja, pl. ac3dsp.c (általános C implementáció), ac3dsp_neon.S (ARM NEON optimalizált Assembly változat).

gyorsabb a hardverközelibb nyelv? Hogy mik vannak....

Vegre egy normalis projekt...

I hate myself, because I'm not open-source.

Erről a 14x gyorsulásról nekem inkább az jut az eszembe, hogy jó béna a C fordító (eseleg maga a C kód) és assembly betétek helyett inkább a fordítót kellene helyrerázni. Na pl az "AI" ilyen helyzetben segíthetne.

Fogadjunk, hogy lesz olyan C fordító, ahol LLM végzi az optimalizálást assemblyre, és akkor visszajutunk oda, hogy mégis jobb magasabb szintű programnyelvet használni.

Miért beszéltek végig úgy, hogy egyik, vagy másik? Szerintem a két véglet egyike sem jó.

A programokban többnyire vannak unalmas részek, mit tudom én, a parancssori kapcsolók értelmezése, ellenőrzése és abból változók kreálása, erre pont jó a C/C++/Python/akármi és van teljesítménykritikus rész, ahol az ember trükközik a memóriával, és olyan varázslatokat valósít meg, amitő a Turbo Pascalon szocializálódott számtek tanár sikítófrászt kapna. Az ilyet szokás asm { ... } blokkban írni. A két nyelv nem versenytárs, hanem kiegészítik egymást.

Form follows function.

Persze, de az FFmpeg egy nagyon speciális eset. Ott érdemes munkát fektetni a kritikus részek kioptimalizálásába, ami feltételezem eleve nem egy monster kód.

Ebben a történetben valami nem kerek. Évekig "optimalizáltam" olyan módon, hogy néztem a C fordító assembly outputot, ahol a futásidő is szerepelt az egyik oszlopban, illetve a függvény végén szerepelt a "straight-line execution time" is. Mivel 6-8 párhuzamos utasítást is tudott a cpu, szépen látszottak a 0 futásidejű* utasítások is. Össze lehetett hasonlítani az egyes C kódok futásidejét. Ha leírtam egy ciklust for vagy while használatával, a fordító "'ertette" mit szeretnék és a két fordulmány között csak annyi különbség volt, hogy egyik esetben az R2 és R3, a másikban az R5 és R7 regiszterekkel készült a ciklus. Megfelelően megfogalmazva assembly szinten szabályozni lehetett a történéseket a C nyelven keresztül.

Aztán ott az a szöveg "Azért használsz assemblyt, hogy optimalizált kódot írjál". Hát nem, mert a mai fordítók ennél jobbak. Én azért írok ilyet, mert megszoktam, átlátom és nem sokkal munkaigényesebb. Ötletesen megfogalmazott makrókkal függvényhívásokat lehet megspórolni, amivel olyan lesz a kód, mint amikor a C-t körberakom egy csomó pragmával.

A fent leírt sebességkülöbséget el sem tudom hinni, mert ilyen eltérés kb. fpu és basic interpreter használata között lehet. ;) 

Ebben az esetben a C fordító valami mást fordít, mint amit leírsz a forrásban. A fordító írójának ismernie kell az adott cpu "szokásait", milyen összetett műveletet "hogyan szoktunk" abban a környezetben megoldani.

Igaz, a fenti tapasztalatokat XLC/IBM C for AIX és POWER* környezetben gyűjtöttem, de akkor is hihetetlen ez a különbség.

*Pl. egy 64 bites változó betöltése 64 biten egy 64 bites loadra fordul, 32 bitesre fordítva 2 db 32 bites load lesz belőle, ahol az egyik utasítás futásideje 0, mert a memória sebessége ugyanaz.

TL;DR: Speciális CPU-utasítások használatáról van szó, tipukusan vektorműveletkről (magyar szóval SIMD), hogy mondjuk nyolc darab 32 bites lebegőpontos számnak egyszerre vegyük a reciprokát.

Node pont ez a jo a compiler intrinsicben, hogy hasznalhatod es azon a platformon, ahol mar van ra tamogatas, ott a meno cuccot kapod, a tobbin meg, ahol meg a gittegylet nem talalta ki 2026-ban, hogy hogy kell kineznie egy SIMD utasitaskeszletnek, ott meg kapod a kezihajtanyos verziot for ciklussal. Majd amikor mar kijott a kozossegi dontes es a forditohoz bekuldik az idevago intrinsic implementaciot, akkor magikusan fel fog gyorsulni az addig lassu kod egy ujraforditas utan.

Nem azt mondom, hogy ez igy mindenkinek feleljen meg (pont az FFMPEG lehet a problemas eset), de szerintem ezzel a tobbseg el tud lenni. En szemely szerint nem terelgetnem fejlesztok szeles retegeit az assembly fele, de megertem, hogy az FFMPEG-nek az o specialis esetukben ez jobban megfelel.

Edit: amugy meg annyit tennek hozza, hogy a cikkben egy kicsit fals analogianak erzem a Rust idecitalasat, mert ennek a problemanak nincs igazan koze a konkret magas szintu nyelvhez. Abban a formaban, ahogy kitalaltak, mar a C is probalt egy olyan absztrakciot csinalni, ami az ilyen szintu dolgokat elfedi. Nyilvan 1970-ben SIMD utasitaskeszletek maximum szuperszamitogepeken leteztek, gondolom nem merult fel, hogy 50 evvel kesobb az emberek videot akarnak nezni a telefonjaikon. Manapsag mar mindegyik "systems programming" nyelv probal mar szabvany szinten fordulni ebbe az iranyba:

https://doc.rust-lang.org/std/simd/index.html

https://en.cppreference.com/w/cpp/experimental/simd.html

Egyetértek azzal amit írtál. :)

Szerintem ebben az esetben a fordító még nem ismerte a RISC vektor utasítás készletét, úgyhogy a felhasználónak a for ciklusos verziót fordítja le. Ehhez képest a vektoriális műveletek ezek szerint akár 14x-es gyorsítást hozhatnak bizonyos spéci esetekben. Ha majd a fordító is megkapja támogatást, akkor az asm előnye jelentősen lecsökken.

Hát, rá is fér, mert b*szott lassú. Minap kellett 2160p-ről 720p-re konvertálnom egy 10 perces videót. Negyed óra után elfogyott a türelem, lelőttem az ffmpeg-et, majd ráeresztettem a mencoder-t, ami pár perc alatt végzett vele!

Kár, hogy már csak hébe-hóba fejlesztik a mencoder-t, mert milliószorta hatékonyabb az ffmpeg-nél. Nyugodtan végezzen mindenki mérést otthon, le fog esni az állatok.

Érdekes téma egyébként, hogy a fordítókat pont azért nehéz fejleszteni, mert ahogy írták sokan, nagyon sok helyzet fordul elő, és majdhogynem külön-külön felkészítik őket 1-1 szituációra.

Jó kérdés viszont, hogy ha csinálsz egy gcc -O3 kódot, és arra egy direkt erre tanított ML-t eresztesz rá, nem lesz-e képes jobb eredményt produkálni, mint egy reszelgetett algoritmikus fordító?

Elnézve, hogy jutottunk LLM-eknél, szerintem de - csak persze nem errefele mentek el, mert nem ez a szűk keresztmetszet az IT-ban, hanem a developer time.

Szerintem rosszul ülünk a lovon. Nem a fordítónak kellene megsejtenie, hogy mire gondolt a költő, hanem explicit meg kellene mondani a kódban, hogy mi legyen. Assembly esetén sem az történik, hogy leír az ember sok utasításból egy ciklust, majd az assembler valami hardware támogatott egyetlen utasítássá fordítja, hanem azt írjuk le, amit szeretnénk.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Nem nagyon kapcsolódik ahhoz, amit írtam. Arról beszéltem, hogy nem valamiféle optimalizációnak kellene megálmodnia, hogy ez a while ciklus egyetlen hardware támogatott utasítással, meg előtte néhány regiszter betöltésével kiváltható, hanem ezen speciális dolgok mögé függvényeket vagy macrokat kellene tenni.

A többivel mi lesz? Semmi. Lassú marad.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A hordozhatóságot nem tudod máshogy biztosítani. Alapvetően szerintem nincs baj azzal, ha a fordító felismer bizonyos szerkezeteket, és tudja, hogy adott arch-on azt hogy szokás hatékonyan csinálni.
Különben kijön egy másik mag, vagy le kell fordítani más arch-ra, és rögtön meg lehet baszni az egészet.

Assembly esetén sem az történik, hogy leír az ember sok utasításból egy ciklust, majd az assembler valami hardware támogatott egyetlen utasítássá fordítja

Dehogynem! Csak el van dugva a processzor hasába, de belül az egész utasítás-frontend rész ezt csinálja. :) A pipeline 80-90%-át az utasítás szétbontó, máshogy összerakó, ütemező, átmasszírozó rész teszi ki.

Régóta vágyok én, az androidok mezonkincsére már!

Én is fordítóról beszélek, hardveresről. :)

<Amúgy nyilván offolás az egész, de ha már lúd, ugye... :) >

Egy jelentős absztrakciós szintugrás van az x86 vagy ARM opkódok és a belső mikro/makroutasítások között. Az előbbi szemantikában feltételezi, hogy az előző utasítás eredménye azonnal a regiszterekben van. Az utóbbi viszont szemantikában feltételezi, hogy valami már "megoldotta", hogy a végrehajtás kezdetekor a helyes bemenő adat ténylegesen előállt. 

Ha programoztál esetleg DSP-t assemblyben, akkor szerintem megvan a pipeline-hossz számolgatós játék, hogy melyik utasítás eredménye hány órajel múlva jelenik meg a célregiszterben. És a kódod innentől nemcsak általában az architektúrára, hanem a konkrét modellre is specifikus. Illetve a gyártó keze meg van kötve, hogy nem változtathat a pipeline hosszán, mert töri a kompatibilitást és onnantól új architektúrának számít. És persze emiatt nem lehet betenni semmi spekulatív meg out-of-order varázslatot, mert ezektől már nem konstans a végrehajtási órajelciklusok száma.

Régóta vágyok én, az androidok mezonkincsére már!

Az utóbbi viszont szemantikában feltételezi, hogy valami már "megoldotta", hogy a végrehajtás kezdetekor a helyes bemenő adat ténylegesen előállt. 

Igy (mikro)architekturalisan minden stage-nak varnia illik azert arra hogy az elozo stage-tol kapjon valamit - vagy azert hogy legyen dolga, vagy azert mert meg amire var az nincs kesz :) De valojaban ezutobbi is csak annyit tesz hogy az elozo stage-tol nem kapja meg a jelzest hogy "na, mehet". 

Inkabb azt mondanam hogy a forditok azert eroteljesen optimalizalnak arra nagyjabol architektura-fuggetlenul hogy "minel elobb legyen a regiszterben az amit minel kesobb kell csak felhasznalni". 
 

"minden stage-nak varnia illik azert arra hogy az elozo stage-tol kapjon valamit"

Nyilván, de ennek a technikai megvalósítása az az - egyáltalán nem triviális - hardveres fordító, ami az x86-os utasításokból jópár közbenső reprezentáción át végül a végrehajtóegységek bemenetére kibocsátható mikroutasítás-szavakat előállítja.

Technikailag a szoftveres fordítók erre relatíve keveset tudnak ráhatni. Létezik ugyan "cost model" a konkrét (modellspecfikus) optimalizáló profilban, ami megmondja az egyes utasításfajták (minimális) latency-jét, illetve hogy hány belső erőforrása van a processzornak és az egyes műveletek ebből mennyit használnak fel. Benchmark eredményeket nézegetve a tapasztalatom az, hogy ezek nagyon marginálisan javítanak a teljesítményen, ha egyáltalán. Volt amikor Zen5-ön a znver4 target adott jobb eredményt a znver5-höz képest... Egyszerűen túlságosan nemdeterminisztikus, túlságosan valós időben derül ki, hogy éppen hogy lesznek foglaltak a végrehajtóegységek (hyperthreadingnél a fordító semmit nem tud megjósolni a másik thread erőforrásfogyasztásáról), éppen a cache-ben mi van benn, mihez kell a memóriához fordulni, melyik row van nyitva éppen a memóriában stb. 

Régóta vágyok én, az androidok mezonkincsére már!

Ha programoztál esetleg DSP-t assemblyben

Bizony...

Regi szep idokben, amikor egy Texas DSP-n nezegettunk FFT teljesitmenyt azt lattuk, hogy egy C kod ~1500 orajel alatt fut le, egy szenne optimalizalt (pipeline szelessege, hossza, utasitasok osszeboronalasa) assemply kod meg ~50 ciklus alatt megvolt. Mas kerdes, hogy elolvasni alig birtuk a kodot, nem hogy megirni :)

x86-ra mar 20+ eve szejjel van optimalizalva asm-ben, es mar akkoriban is voltak arm-es patchek is hozza. az swscale (ami eredetileg az mplayerhez keszult) ugy lett megirva, hogy runtime generalja le gepi kodban a szukseges konvertalot, es azt futtatja. nyilvan mindenre van C fallback az egzotikus arch-ok miatt, ebben az esetben is az tortent ha jol ertem, hogy egy gcc altal kevesbe jol optimalizalt cpu-ra inkabb atirtak kezzel asm-re a kodot.

"... ugy lett megirva, hogy runtime generalja le gepi kodban a szukseges konvertalot, es azt futtatja."

Szerintem nem generál le semmit. Benne van a különböző utasításkészlető gépi kód + C. Futási időben detektálja a CPU-t és az alapján futtatja valamelyik assembly vagy C-s változatot.

Pl.:

av_cold void rgb2rgb_init_x86(void)
{
   int cpu_flags = av_get_cpu_flags();
#if HAVE_INLINE_ASM
   if (INLINE_MMXEXT(cpu_flags))
       rgb2rgb_init_mmxext();
   if (INLINE_SSE2(cpu_flags))
       rgb2rgb_init_sse2();
   if (INLINE_AVX(cpu_flags))
       rgb2rgb_init_avx();
#endif /* HAVE_INLINE_ASM */

 

Egyébként ez tipikusan az az eset amit a fordító magátol nem tud jól kezelni. Vagy lesz optimalizáció adott CPU-ra, de a többin (ami nem támogatja az összes optimalizálásban használt CPU utasítást) nem fog futni a program, vagy minden CPU-n fut, de nincs optimalizáció.

CPU függő esetben meg vagy az egész binárisból lesz több változat így többszörös méret vagy minden egyes optimalizáció előtt egy CPU ellenőrzés. Utóbbi estben meg az optimalizált gyorsítást lassítja előtte az ellenőrzés.

A kompromisszumos megoldás, hogy csak ott legyen több optimalizált változat, ahol erre szükség van. Ezt meg a programozó tudja a fordító nem, hogy x függvény csak minden hónapban egyszer y meg minden képkocka mindet pixeljére lefut. Előbbi esetben jó az összes CPU-n futó optimalizálatlan változat, addig utóbbiból meg több optimalizált változat közül kell választani, de pl. képkockánként/soronként csak egyszer a pixeles rész már külön-külön optimalizálva egy CPU ellenörzés mögött.

Szerintem nem generál le semmit.

de

https://github.com/FFmpeg/FFmpeg/blob/master/libswscale/x86/ops.c

Benne van a különböző utasításkészlető gépi kód + C

igen, sok mindent (pl colorspace konverziok) fixen meg lehet irni, bar pl ott is van trukkozes, csak ott forditasi idoben generalja le templatebol az asm kodokat :)   

https://github.com/FFmpeg/FFmpeg/blob/master/libswscale/x86/swscale_template.c

de pl. az atmeretezest nem lehet altalanosan jol optimalizalni, ezeket generalta mar 25 eve is futasi idoben.

Az asm nagy királyság, de buktatója, hogy architektúra, azon belül is generációfüggő, épp milyen utasítások állnak rendelkezésre, amelyek mentén lehet optimalizálni. Persze, ha az Alibabaésangyvenrablósok ráérnek minden architektúra minden generációjára kireszelni a legoptimálisabb asm kódot, akkor megemelem a nem létező kalapom, de legyünk reálisak, a C az, ami portolható, kenyérpirítóra is.

“Linux isn't an OS, it's a troubleshooting sim game.” (a YouTube commenter)

C-ben meg van irva minden mar, azt nem torlik ki, csak lesz asm alternativa is. Regen is, most is vannak olyan felhasznalasok, ahol minden orajel szamit, mert nem azt nezik hogy neked a pc-den mennyi ido lesz atkonvertalni a csaladi videoidat, hanem mondjuk napi millios mennyisegben konvertaljak egy youtube-tiktok-videa-stb meretu site forgalmat vele, es nem mindegy 10%-al kevesebb szukseges vas sem mert az is akar 10000 db gepet jelent.

MCU-n nálunk is vannak olyan alkalmazások, amiket asm-ben kell megírni. Nem a sebesség, hanem a kiszámíthatóság miatt. Órajelre tudjuk, mikor mi történik. Real-time.

Nekem azzal van a bajom, amikor egy fentihez hasonló esetből (speciális helyzetre speciális megoldás) egyesek azt a következtetést vonják le, hogy lám, ez a jó irány, ezt kellene máshol is csinálni Rust-osodás helyett.
Ilyenkor kiáltok fel, hogy MI A FASZ?!