C++ och dess framtid att programmera minnessäkert - Hur går utvecklingen?

Permalänk
Medlem
Skrivet av orp:

Vilket skitsnack... Om man är Python-utvecklare så är man tränad i att skriva kod och varför skulle man inte förstå hur grep, indexering och sökning fungerar för att man kodar Python? Varför skulle man förstå hur grep, indexering och sökning fungerar bättre för att man kodar C++?

Att bara komma på tanken att skriva 250 000 rader kod i python är helgalet. De utvecklare som satsar kommer välja andra språk

Programmerare som utvecklas väljer självklart verktyg där de kan prestera bättre

Permalänk
Medlem
Skrivet av klk:

I de allra flesta fall använder programmerare som inte vet hur en processor jobbar en massa bibliotek och det är också något jag placerar i facket "deklarativ programmering" vilket enligt mig inte handlar om programmering utan att pussla ihop färdiga lösningar.

All programmering handlar om att pussla ihop färdiga lösningar. Men man kan göra det på många olika nivåer.
Allt från att koppla ihop elektroniska komponenter på ett kretskort till att ge kommandon till en AI, och allt däremellan.
Men tänket är i stort sett detsamma - hur man bryter ner ett problem till komponenter som man har färdiga lösningar till, och hur man pusslar ihop de till en lösning.

Permalänk

Det finns lite hyfsat stora Open Source projekt med rätt store kodbaser i Python. Är allt detta skrivet av losers som inte vet vad de håller på med?

Project Estimated LOC (Python only) Notes
Django ~350,000+ Very well-structured, includes ORM, template engine, and full-stack features.
Home Assistant ~600,000+ Huge codebase due to massive integration support (each device/component adds code).
pandas ~160,000+ (Python) + ~300,000+ (C/Cython) Core performance relies heavily on C/Cython.
Biopython ~90,000+ Lightweight but broad bioinformatics functionality.
spaCy ~40,000+ (Python) + ~120,000+ (Cython/other) Efficient and streamlined for speed and production use.
pytest ~30,000–40,000 Core is lean but very modular and extensible via plugins.
yt-dlp ~100,000+ A fork of youtube-dl with many extractors for sites. Mostly Python.
Sphinx ~70,000–90,000 Includes reStructuredText parsing and a plugin system.
OpenCV-Python ~15,000–25,000 (bindings) Most heavy lifting done in OpenCV C++ core; Python is just the glue.
Scrapy ~60,000–80,000 Async crawler, well-structured, with middleware and extension support.

Permalänk
Medlem
Skrivet av klk:

Att bara komma på tanken att skriva 250 000 rader kod i python är helgalet. De utvecklare som satsar kommer välja andra språk

På vilket sätt skulle python vara sämre för stora projekt än C++?
Vad är det med C++, enligt dig, som skulle göra det bättre lämpat?
Skillnader i själva språken alltså, så kom inte yrande med någonting irrelevant om "C++ programmerare" eller "python programmerare".

Permalänk
Medlem
Skrivet av Erik_T:

På vilket sätt skulle python vara sämre för stora projekt än C++?

Först och främst så är det skriptspråk, otroligt långsamt och enkeltrådat (GIL). Bara där har du utvecklare som blir bakbundna.
Sedan är hela språket anpassat för att använda komponenter och de flesta vana utvecklare vet om saker som teknisk skuld och hur riskabelt det är att göra sig beroende, alla sådana beroende måste övervägas.

Skrivet av Erik_T:

Vad är det med C++, enligt dig, som skulle göra det bättre lämpat?

Frihet, du kan göra precis vad du vill. C++ design är också mer korrekt sett till objektorientering och annat jämfört med de flesta andra språken.

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Django ~350,000+ Very well-structured, includes ORM, template engine, and full-stack features.

Har du kollat Django? Hur menar du att django skulle behöva 350 tusen rader kod. de kanske räknat dokumentation som kod möjligen. annars förstår jag inte

Tror det är mindre än 50 000 (kanske inte ens 25 000) som är riktig kod

Permalänk
Medlem
Skrivet av klk:

Har du kollat Django? Hur menar du att django skulle behöva 350 tusen rader kod. de kanske räknat dokumentation som kod möjligen. annars förstår jag inte

Tror det är mindre än 50 000 (kanske inte ens 25 000) som är riktig kod

Oavsett så har du Home assistant... Sluta yra bara för att du har blivit kränk över att dom valde Python före C++ på din arbetsplats.

Permalänk
Medlem
Skrivet av klk:

Frihet, du kan göra precis vad du vill.

Frihet är ju också oerhört begränsande.

Vi kan, om inte annat så för argumentationens skull, anta att du har rätt i att C++ är bäst.

99 ggr av 100 så kommer andra utvecklare slå dig på fingrarna med sina undermåliga produkter (med produkter i det här fallet menar jag språk) eftersom du utan undantag försöker lösa alla problem som att dom är spikar, eftersom det enda verktyg du har är en hammare.

Skrivet av klk:

Och det är därför som C/C++ utvecklare har svårt att diskutera med "andra" programmerare.

Den här typen av uttalande, och dom har vi ju sett ett antal gånger från dig, är väldigt talande.

Det du säger är ju att du har svårt att prata med andra programmerare.
Har du funderat på om det kan ha helt andra förklaringar än vilket språk som har valt att utveckla i?

Försök angripa problemet som en utvecklare, vilken är den (minsta) gemensamma nämnaren?

Du har 10 klasser, 9 av dom fungerar sinsemellan, utan problem, men så fort du introducerar den där 10e klassen, så uppstår det alltid problem. Som utvecklare, var skulle du börja för att lösa det problemet?

Permalänk
Datavetare
Skrivet av klk:

Har du kollat Django? Hur menar du att django skulle behöva 350 tusen rader kod. de kanske räknat dokumentation som kod möjligen. annars förstår jag inte

Tror det är mindre än 50 000 (kanske inte ens 25 000) som är riktig kod

Well, i det här fallet är det ju trivialt att checka facit

$ git clone https://github.com/django/django.git $ sloccount django ... SLOC Directory SLOC-by-Language (Sorted) 253015 tests python=253015 107441 django python=107441 548 docs python=548 293 scripts python=293 0 extras (none) 0 js_tests (none) 0 top_dir (none) Totals grouped by language (dominant language first): python: 361297 (100.00%) Total Physical Source Lines of Code (SLOC) = 361,297

Det skrivet så är ju "bara" 100k av rader del av produkten, 250k är tester.

HA

$ git clone https://github.com/home-assistant/core.git $ sloccount core ... SLOC Directory SLOC-by-Language (Sorted) 1069948 tests python=1069937,sh=11 860119 homeassistant python=860119 10463 script python=10324,sh=139 4019 pylint python=4019 28 rootfs sh=28 0 machine (none) 0 top_dir (none) Totals grouped by language (dominant language first): python: 1944399 (99.99%) sh: 178 (0.01%) Total Physical Source Lines of Code (SLOC) = 1,944,577

Här är 860k del av produkten och 1M är tester.

Skulle ändå säga: det är ju inte gigantiska produkter. Har på rätt mycket egen hand skrivit projekt i C där det ena var ~120k rader kod och det andra ca 300k rader. Båda som del i ett större projekt med åtskilliga miljoner rader. Hur hittar man saker där?

Typ "grep" samt man lär sig de delar man frekvent interagerar med.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk

Min bild av C++ var att det var detta språk alla programmerade för på högskolan, exakt vad förr är kan diskuteras men 20år tillbaka. Idag så vet jag inte vad de gör på skolor, i arbetslivet är dock oftast cash the king.
De vill ha en så billig och bra lösning som möjligt, c++ är inte alltid detta av flera orsaker.
Onödigt krångligt, onödigt risker för fel. Ofta behövs inte denna prestandaökning som en C++ lösning hade gett.

Skrivet av Xeonist:

Frihet är ju också oerhört begränsande.

Vi kan, om inte annat så för argumentationens skull, anta att du har rätt i att C++ är bäst.

99 ggr av 100 så kommer andra utvecklare slå dig på fingrarna med sina undermåliga produkter (med produkter i det här fallet menar jag språk) eftersom du utan undantag försöker lösa alla problem som att dom är spikar, eftersom det enda verktyg du har är en hammare.

Jag tänker även att låt oss säga man är lika effektiv i C++ som C#, Java, pyton etc.
Då kan man få ett problem som kanske är roligt när man är en junior och det är att skapa en lösning där bara man själv på företaget effektivt kan underhålla den, man har blivit oumbärlig. Jippi. Skitskoj ! Detta tills man inser att det innebär att man måste vara tillgänglig och åtgärda problem 365 dagar på året.
Och man inser att det är bättre att göra en lösning som innebär att man själv inte måste göra allt med superkorta varsel och de vill ha det löst på någon timma. Denna lösning bör vara så enkel som möjligt speciellt i tider när folk byter jobb så ofta.
*edit*
Med onödigt avancerade lösningar så tro inte byta jobb hjälper, ni kan bli kontaktad ändå. Då får man ej tid rapportera denna tid och man kan säga nej, men det tar ändå tid och kraft.

Permalänk
Datavetare
Skrivet av klk:

Först och främst så är det skriptspråk, otroligt långsamt och enkeltrådat (GIL).

Det är inte nödvändigtvis sant. Dels har man, tillslut..., verkligen börjat jobba på att få bort GIL. I aktuell release, Python 3.13 som släpptes hösten 2024, är GIL delvis bortta.
https://medium.com/@mitesh.singh.jat/gil-becomes-optional-in-...

Hur fort man kan jobba vidare beror på hur bra/dåligt det går (har inte jättebra koll, ser storheten i Python och inser att det inte finns något annat vettig val när man jobbar med ML, men använder det så lite som möjligt då jag personligen kraftigt fördrar statiskt typade kompilerade språk) så kan GIL vara historia redan i 3.14.

Men redan tidigare finns ju en lång rad populära bibliotek där man sedan länge både haft god skalning med CPU-kärnor, t.ex. NumPy och Numba, samt GPU, t.ex. PyTorch, Tensorflow och nu senaste Numba-CUDA.

Väldigt enkelt exempel med NumPy

import numpy as np import time n = 5_000 A = np.random.rand(n, n).astype(np.float32) B = np.random.rand(n, n).astype(np.float32) print("Starting matrix multiplication...") start = time.time() C = np.dot(A, B) # or A @ B end = time.time() print(f"Completed in {end - start:.2f} seconds") print(f"Result shape: {C.shape}")

ger detta på en Orange Pi 5, de 4 "stora" kärnorna

$ for cpu_mask in 0x10 0x30 0x70 0xf0; do echo "Running with CPU mask $cpu_mask"; time taskset $cpu_mask python main.py; done Running with CPU mask 0x10 Starting matrix multiplication... Completed in 8.02 seconds Result shape: (5000, 5000) real 0m9.123s user 0m8.614s sys 0m0.507s Running with CPU mask 0x30 Starting matrix multiplication... Completed in 3.89 seconds Result shape: (5000, 5000) real 0m4.941s user 0m8.396s sys 0m0.525s Running with CPU mask 0x70 Starting matrix multiplication... Completed in 2.72 seconds Result shape: (5000, 5000) real 0m3.795s user 0m8.907s sys 0m0.474s Running with CPU mask 0xf0 Starting matrix multiplication... Completed in 2.05 seconds Result shape: (5000, 5000) real 0m3.110s user 0m9.017s sys 0m0.518s

Inte perfekt skalning, men helt OK framförallt givet hur väldigt "matlab:igt" NumPy är

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av klk:

Först och främst så är det skriptspråk, otroligt långsamt och enkeltrådat (GIL). Bara där har du utvecklare som blir bakbundna.
Sedan är hela språket anpassat för att använda komponenter och de flesta vana utvecklare vet om saker som teknisk skuld och hur riskabelt det är att göra sig beroende, alla sådana beroende måste övervägas.

Senast jag tittade så var C++ också enkeltrådat. Liksom den stora majoriteten av övriga programmeringsspråk.
Så otroligt långsamt är ju inte python, men oavsett om det är det eller inte så har det ju väldigt lite att göra med möjligheterna att skapa stora projekt.

Det är möjligt att python gör det enklare att använda externa bibliotek och komponenter än vad C++ gör, men isåfall är det ju bara ett plus i kanten för python. Det finns absolut ingenting i python som tvingar dig att använda externa komponenter i högre utsträckning än vad C++ gör.

Citat:

Frihet, du kan göra precis vad du vill. C++ design är också mer korrekt sett till objektorientering och annat jämfört med de flesta andra språken.

Mer korrekt? På vilket sätt då?
Python är ungefär lika objektorienterat som C++, dvs de är bägge i grunden imperativa språk med påklistrat stöd för objektorienterad programmering.

Sen kan man ju diskutera om det är bra att stödja objektorienterad programmering. Det är det inte enligt mig, då objektorienterad programmering - så som det vanligtvis lärs ut och används - mest är dumheter som skapar fler problem än det löser

Permalänk
Medlem
Skrivet av lillaankan_i_dammen:

Min bild av C++ var att det var detta språk alla programmerade för på högskolan, exakt vad förr är kan diskuteras men 20år tillbaka. Idag så vet jag inte vad de gör på skolor, i arbetslivet är dock oftast cash the king.

Vilket språk som används på universitet/högskola varierar både med vilken man läste och när. (Och naturligtvis vilken skola)
På ingenjörsutbildningarna som sällan går så djupt in på programmering så brukar man bara lära sig ett eller två språk, och då väljer de språk som just då är populära i arbetslivet. Långt tillbaka (och fortfarande på en del kurser) så var det Fortran. Pascal har också förekommit. Senare bytte man till C++, och sen till Java. Osäker på vad som används som introduktionsspråk idag. Gissningsvis C# eller Python.

På datavetarutbildningarna däremot så har man föredragit funktionella språk som introduktion. Lisp/Scheme om man går tillbaka några decennier, senare bland annt Standard ML, och jag tror Haskell är rätt poppis nuförtiden på sådana utbildningar.

I arbetslivet så beror det ju på exakt vad man jobbar med, men nuförtiden så verkar det mesta vara webb-baserade lösningar där man inte använder C/C++ i vare sig frontend eller backend.

Permalänk
Medlem
Skrivet av Xeonist:

Frihet är ju också oerhört begränsande.

Varför och för vem är frihet begränsande?
Du tycker inte det hänger samman med skicklighet i specifikt område.
Ritar jag cad (vilket jag räknar mig till nybörjare för) vill jag gärna ha enklare cad program med kommandon i programmet som ger mig hjälp. Vana konstruktörer tror jag önskar flexibilitet och frihet, för dem är enkelheten begränsande.
Eller ta ett vanligt program, photoshop. För nybörjare är det programmet svårt medan skickligare behöver kunna ställa in och ha frihet och göra det.

Skrivet av Xeonist:

Vi kan, om inte annat så för argumentationens skull, anta att du har rätt i att C++ är bäst.

Bäst för utvecklare med stort intresse, annars bör de välja annat

Skrivet av Xeonist:

99 ggr av 100 så kommer andra utvecklare slå dig på fingrarna med sina undermåliga produkter (med produkter i det här fallet menar jag språk) eftersom du utan undantag försöker lösa alla problem som att dom är spikar, eftersom det enda verktyg du har är en hammare.

Stämmer inte, bara att titta på kommersiell mjukvara. I 9 fall av 10 bygger det mesta på C/C++ vilket är trist, språket har för hög dominans. Under en hel massa år hände ingenting med språket eller knappt ens kompilatorer. Så kom C++11 och det var ett fantastiskt lyft. C++ utvecklas idag och C++26 är återigen en stor uppdatering. Speciellt för att skriva generell kod.

Skrivet av Xeonist:

Den här typen av uttalande, och dom har vi ju sett ett antal gånger från dig, är väldigt talande.

Kanske för att det är korrekt

Skrivet av Xeonist:

Det du säger är ju att du har svårt att prata med andra programmerare.
Har du funderat på om det kan ha helt andra förklaringar än vilket språk som har valt att utveckla i?

Vet du något annat språk som så bra kan abstrahera funktionalitet och bibehålla prestanda?

Skrivet av Xeonist:

Försök angripa problemet som en utvecklare, vilken är den (minsta) gemensamma nämnaren?
Du har 10 klasser, 9 av dom fungerar sinsemellan, utan problem, men så fort du introducerar den där 10e klassen, så uppstår det alltid problem. Som utvecklare, var skulle du börja för att lösa det problemet?

Och för att lösa problemet så bra som möjligt är det bra med frihet

Om jag då tar ett exempel från verkligheten för att beskriva hur C++ utvecklare ofta tänker.
Följande förutsättningar gäller.
En lösning kräver mycket hög prestanda och måste skala till så många kärnor som möjligt. För att lyckas skala till många kärnor delas data upp i "tårtbitar" om uttrycket tillåts. Mindre isolerade enheter. Varje liten den kan jobba isolerat innan det synkas.

För att lösa det krävs en hel del kod endast för att beräkna hur arbeten skall delas upp, både vad gäller data och hur många tårtbitar. Programmet får inte kompileras om, en installation måste fungera i många olika sammanhang.
Alla "rörliga delar" flyttas därför ut och görs så enkla som möjligt så programmet blir användbart.

Spel ser ofta ut så här, de måste vara mycket snabba samtidigt som flexibilitet är viktigt. Grafikdelen är därför hårt optimerad samtidigt som de har en del som är flexibel (skapa grafik och regler i spelet). Spelmotorn är i C++ medan regler och data genererats med annat (ofta Lua eller C#).

Angående tårtbitsexemplet ovan. Beräkningar av data kan inte göras av utvecklare. Det är metadata som programmet läser in. Alltså text och denna text processas i programmet av C++ kod och görs om till instruktioner som sedan processas

Kan se ut så här

auto valueResult = gd::expression::token::calculate_s("length( text )", { {"text", "0123456789012345"} }); auto valueResult = gd::expression::token::calculate_s( "10 - -10" ); auto valueResult = gd::expression::token::calculate_s("min( 100, 200 ) + 999 + max( 10, 30 )"); auto valueResult = gd::expression::token::calculate_s( "10 >= x", {{"x", 10}} );

Snabbheten och friheten i C++ tillåter en flexibel lösning där anpassning av programmet kan göras av personer som inte har en aning om hur man skriver kod.

Permalänk
Datavetare
Skrivet av klk:

C++ design är också mer korrekt sett till objektorientering och annat jämfört med de flesta andra språken.

Du har tidigare skrivit i tråden att en dålig egenskap hos programvara är hårda beroenden ("strong couplings"). Givet detta, med vilken definition är OO-modellen vald i C++ "mer korrekt"?

Det finns typ 3 huvudklasser av OO (man kan argumentera kring den sista här)

Typ-baserad: bl.a. C++, Java, C#, Simula
Prototyp-baserad: främst JS, men är väldigt enkelt att stöda detta i Python, Ruby och Clojure (säkert flera också)
Duck-typed: Go, Python, Ruby, JS, Clojure

Några väldigt utmärkande saker för varje model
Type-based: "Behavior sharing" via arv, polymorfism bundet till typ, normalt statisk typ-check (vilket underlättar för saker som intellisense)
Prototyp-baserad: "Behavior sharing" via delegation, polymorfism via prototyp-uppslagning, normalt dynamisk typ-check (men finns hjälpmedel som TS och "type-hints" i Python m.fl.)
Duck-typed: "Behavior sharing" via composition, polymorfism extremt flexibelt och exakt funktion varierar (Clojure är extremt kraftfullt här), normalt dynamiskt typ-check med Go som modernt exempel på hur elegant man ibland kan lösa något när man faktiskt "hittat boxen" och kan designa från det

Är inte lite konsensus kring OOP att man ska så långt som möjligt föredra "composition" (has-a) över arv (is-a)? D.v.s. "korrekt OO" uppmuntras i större utsträckning i de språk som använder duck-typing. Detta då arv ger väldigt starka binding (något som man bör undvika) samt att utanför skolboksexempel får man nästan alltid med sig "skit som inte är användbart" vid arv.

Den person som först myntade uttrycket OOP, Alan Kay, har bl.a. sagt detta

"I invented the term object-oriented, and I can tell you that C++ wasn't what I had in mind"

Hans definition ligger mest i linje med prototyp-based. Skulle själv hävda att duck-typed egentligen inte i sig är OO, det råkar bara vara en model som är så flexibel att den även inrymmer OOP.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Yoshman:

Du har tidigare skrivit i tråden att en dålig egenskap hos programvara är hårda beroenden ("strong couplings"). Givet detta, med vilken definition är OO-modellen vald i C++ "mer korrekt"?

Bara för att C++ är det språk som bäst stödjer OOP så menar jag inte att det är en bra teknik att lösa saker på, framförallt på grund av coupling

Har sett några program refaktorerats till OOP när det var hett och fullständigt skrivits sönder

Permalänk
Medlem
Skrivet av Erik_T:

Mer korrekt? På vilket sätt då?
Python är ungefär lika objektorienterat som C++, dvs de är bägge i grunden imperativa språk med påklistrat stöd för objektorienterad programmering.

Fråga något AI verktyg, att jag skall behöva förklara skillnader mellan C++ och Python i tråden visar bara på hur lågt nivån sjunkit

Permalänk
Datavetare
Skrivet av klk:

Stämmer inte, bara att titta på kommersiell mjukvara. I 9 fall av 10 bygger det mesta på C/C++ vilket är trist, språket har för hög dominans. Under en hel massa år hände ingenting med språket eller knappt ens kompilatorer. Så kom C++11 och det var ett fantastiskt lyft. C++ utvecklas idag och C++26 är återigen en stor uppdatering. Speciellt för att skriva generell kod.

Backar vi 20-25 år så håller jag helt med här, C++ totaldominerade kommersiell programvara på den tiden.

Men stämmer det idag? Kollar jag på programmen jag ofta kör

ChatGPT: TS/Electron (det på Windows/MacOS)
Chrome: C++
Discord: TS/Electron
Pixelmator Pro: Swift
Safari: C++/Obj-C (typ "backend" i C++ och "frontend" i Obj-C/Webkit)
Slack: TS/Electron
Visual Studio Code: TS/Electron
Visual Studio: C++/C# (typ "backend" i C++ och "frontend" i C#/WPF)
Xcode: Obj-C/Swift (det var initialt i Obj-C, men flyttas gradvis till Swift, kompilatorer/debugger är C++ men de är separata binärer)

Och kan förstå detta. Börjar man utveckla en desktop-applikation 2025 är behöver man tänka på mer än Windows då det inte alls har några >90 % av marknaden. TS/Electron är nog det vettigaste valet då man rätt automatiskt stödjer Windows, MacOS och Linux samt får en mycket enkelt väg till att stödja webb, iOS och Android.

Spel är exempel på något som väldigt ofta fortfarande är i C++. Att de fortfarande är i C++ är en väldigt stor anledning till att de också blir "Windows only". Vill man stödja fler plattformar är detta klart enklast med Unity (C#), går även med UE4/5 men är lättare att gå bort sig jämfört med Unity.

Så det är definitivt ingen självklarhet att skriva applikationer i C++ längre. Givet att mobilerna idag är största "konsumentplattform" lär ju Swift (primärt språk för iOS) och Java/Kotlin (Java historiskt, men sedan 2019 sa man på Google I/O att Kotlin bör vara förstaval) idag stå för en väldigt stor andel.

Skrivet av klk:

Vet du något annat språk som så bra kan abstrahera funktionalitet och bibehålla prestanda?

Hmm, du har redan fått flera konkreta exempel där Rust slår C++ på fingrarna i prestanda. Det trots att man får rätt mycket extra garantier i Rust.

Men för att svara på din specifika fråga, ett axplock av språk där hög prestanda är en av fokuspunkterna

  • C#

  • Go

  • Java

  • Kotlin

  • Rust

  • Scala

  • Swift

Utelämnade C, Fortran och Zig. Alla dessa kan ge riktigt hög prestanda, men alla är "lower-level than C++".

Skrivet av klk:

Spel ser ofta ut så här, de måste vara mycket snabba samtidigt som flexibilitet är viktigt. Grafikdelen är därför hårt optimerad samtidigt som de har en del som är flexibel (skapa grafik och regler i spelet). Spelmotorn är i C++ medan regler och data genererats med annat (ofta Lua eller C#).

Spel är faktiskt rätt usla på att effektivt utnyttja många CPU-kärnor. Inte för att folk är inkompetenta, utan främst av två orsaker

1. det är, undantaget det som redan körs på GPU, ett problem som inte innehåller gigantisk mängd parallellism. Och när det finns blir man ofta begränsad av att behöva sync:a en gång per frame. Ju längre man kan hålla saker separerade, ju bättre. Den praktiska gränsen för när overhead att sprida saker över kärnor kontra vinsten från ökad kapacitet dikteras av Amdahls lag och ligger rent praktiskt runt 1ms strecket (man tappar "nära perfekt skalning" långt tidigare, under detta är det ofta rätt meningslöst att sprida över kärnor).
2. spelmotorer är väldigt stora och komplexa, samtidigt som de flesta började sina liv långt innan multicore CPUer var standard. Det finns helt klart friktion här.

Och tar man det allmänt tillgängliga fall som ändå finns där man hyfsat enkelt kan utnyttja CPU-kärnor i spel finns Unity:s DOTS/ECS. Där skriver man alltså i C#, inte C++...

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Datavetare
Skrivet av klk:

Om jag då tar ett exempel från verkligheten för att beskriva hur C++ utvecklare ofta tänker.
Följande förutsättningar gäller.
En lösning kräver mycket hög prestanda och måste skala till så många kärnor som möjligt. För att lyckas skala till många kärnor delas data upp i "tårtbitar" om uttrycket tillåts. Mindre isolerade enheter. Varje liten den kan jobba isolerat innan det synkas.

För att lösa det krävs en hel del kod endast för att beräkna hur arbeten skall delas upp, både vad gäller data och hur många tårtbitar. Programmet får inte kompileras om, en installation måste fungera i många olika sammanhang.
Alla "rörliga delar" flyttas därför ut och görs så enkla som möjligt så programmet blir användbart.

Bröt ut denna, detta är helt klart en av mina "darlings". Spenderade väldigt mycket tid på detta under 2010-talet!

Tror tyvärr för din egen del att detta är ett fall där du "tänker som en C++-programmerare från 90-talet". Detta är ett mycket komplex område, men det är också ett område det skett enormt mycket utveckling från början av 2010-talet fram till nu (och sker forfarande mycket, man har långt ifrån "löst" detta än).

Låt oss vara konkreta och använda "leksaksexempel" för att visa hur man kan lösa detta på olika sätt. Något som ofta används i exemplen här är den "matematiskt korrekta, men effektivitedtsmässigt korkade implementationer av att beräkna Fibonacci-serien".

I C/C++

int fib(int n) { if (n < 2) return n; return fib(n - 1) + fib(n - 2) }

Den är användbart i illustrationer av flera skäl. Dels är den otroligt enkel i sin implementation, den väldigt mycket resurser att beräkna vid relativt små värden på "n", den går att köra parallellt dels över individuella indata (den är "pure functional") men också köras parallellt internt då varje rekursivt anrop också är helt oberoende.

Med Rust är det direkt trivialt att få ur alla perspektiv "perfekt" skalning med CPU-kärnor om man vill beräkna Fibonacci över en serie värden. Ser ut så här

Klicka för mer information

use rand::Rng; use rayon::prelude::*; use std::time::Instant; const PAR_THRESHOLD: u32 = 30; fn serial_fib(n: u32) -> u32 { if n <= 1 { return n; } serial_fib(n - 1) + serial_fib(n - 2) } fn parallel_fib(n: u32) -> u32 { if n < PAR_THRESHOLD { return serial_fib(n); // Too much parallellism will kill performance, Amdahl shows again... } let (fib_n1, fib_n2) = rayon::join( || parallel_fib(n - 1), || parallel_fib(n - 2)); fib_n1 + fib_n2 } fn main() { let num_elements = 1000; let ser_min_n = 30; let ser_max_n = 36; let par_n = 49; let mut rng = rand::rng(); let ns: Vec<u32> = (0..num_elements) .map(|_| rng.random_range(ser_min_n..=ser_max_n)) .collect(); let start_serial_series = Instant::now(); let _: Vec<u32> = ns .iter() .map(|&n| serial_fib(n)) .collect::<Vec<u32>>(); let duration_serial = start_serial_series.elapsed(); println!( "Serial execution time of {} elements: {:?}", num_elements, duration_serial ); let start_parallel_series = Instant::now(); let _: Vec<u32> = ns .par_iter() // <--- Only change required to run in parallel! .map(|&n| serial_fib(n)) .collect(); let duration_parallel = start_parallel_series.elapsed(); println!( "Parallel execution time of {} elements: {:?}", num_elements, duration_parallel ); let start_serial_fib = Instant::now(); let _ = serial_fib(par_n); let duration_serial_fib = start_serial_fib.elapsed(); println!( "Serial Fibonacci execution time for n = {}: {:?}", par_n, duration_serial_fib ); let start_parallel_fib = Instant::now(); let _ = parallel_fib(par_n); let duration_parallel_fib = start_parallel_fib.elapsed(); println!( "Parallel Fibonacci execution time for n = {}: {:?}", par_n, duration_parallel_fib ); }

Visa mer

Resultat från min dator med 12 "P-kärnor" och 4 "E-kärnor"

Serial execution time of 1000 elements: 13.501740667s Parallel execution time of 1000 elements: 1.076859417s Serial Fibonacci execution time for n = 49: 19.009579541s Parallel Fibonacci execution time for n = 49: 1.493294458s

Ovan exempel är logiskt rätt lätt att översätta till Go (channels+goroutines), C#(TPL/Parallel.For). Båda ser riktigt bra skalning, men det når inte riktigt upp till Rust/Rayon.

Går även att göra med OpenMP i C, C++ och Fortran. Här är effektiviteten nära till lika med Rayon, men är i min mening långt mer komplicerat och otroligt lätt att gå bort sig i exakt hur/var man stoppar in sina "#pragma omg..." direktiv för att resultatet ska bli det man vill ha...

I teorin kan det första fallet göras i standard C++17 och framåt. I praktiken tycker jag std::execution::* så här långt både haft brister i prestanda och är inte alls säkert att det överhuvudtaget gör något (i.e. det kompilerar men inget körs parallellt, det är bara "hints" så korrekt enligt C++17 spec).

Sannolikheten att du lyckas göra något eget som matchar det som är inbyggt i Go, C#, Java, m.fl. och som implementeras av bibliotek som Rust/Rayon, C/C++/Fortran/OpenMP är väldigt väldigt nära noll.

Och håller du inte med om att med något som Rust Rayon är det inte bara "minnessäkert", det är faktiskt hyfsat enkelt också!

Fråga: hur löser en C++-programmerare detta, om vi tar bort OpenMP (där vet jag hur man gör)?

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Skrivet av Yoshman:

... långt mer komplicerat och otroligt lätt att gå bort sig i exakt hur/var man stoppar in sina "#pragma omg..." direktiv för att resultatet ska bli det man vill ha...

Var det en freudian slip eller en medveten felskrivning? Hur som helst så är det tveklöst det bästa inlägget i tråden hittills. LOL! Det beskriver verkligen hur det känns att försöka göra något icketrivialt med OpenMP

Permalänk
Medlem
Skrivet av Yoshman:

Backar vi 20-25 år så håller jag helt med här, C++ totaldominerade kommersiell programvara på den tiden.

Men stämmer det idag? Kollar jag på programmen jag ofta kör

ChatGPT: TS/Electron (det på Windows/MacOS)
Chrome: C++
Discord: TS/Electron
Pixelmator Pro: Swift
Safari: C++/Obj-C (typ "backend" i C++ och "frontend" i Obj-C/Webkit)
Slack: TS/Electron
Visual Studio Code: TS/Electron
Visual Studio: C++/C# (typ "backend" i C++ och "frontend" i C#/WPF)
Xcode: Obj-C/Swift (det var initialt i Obj-C, men flyttas gradvis till Swift, kompilatorer/debugger är C++ men de är separata binärer)

Vilket av de är inte C++ menar du? Electron är C++ för att ta ett exempel.

Ofta är grunden C/C++ med tunna skal över. För vad som hänt senaste 10-15 åren är att vissa produkter blivit extremt populära, exempelvis browserlösningar och då har man byggt tunna skal på dem. Dessa "skal" skrivs med enklare språk

Permalänk
Medlem
Skrivet av Yoshman:

I C/C++

int fib(int n) { if (n < 2) return n; return fib(n - 1) + fib(n - 2) }

Kan du utveckla hur det exemplet är relevant?
Jag tror många utvecklare som försöker dra nytta av alla kärnor hade jublat om de haft så enkla uppgifter

Vet du vad som ofta orsakar gråa hår för de som försöker parallellisera arbeten?

Ledtråd: Ta en så enkel sak som att läsa in CSV formaterad text, varför är den uppgiften svår att parallellisera?

Permalänk
Datavetare
Skrivet av klk:

Vilket av de är inte C++ menar du? Electron är C++ för att ta ett exempel.

Ofta är grunden C/C++ med tunna skal över. För vad som hänt senaste 10-15 åren är att vissa produkter blivit extremt populära, exempelvis browserlösningar och då har man byggt tunna skal på dem. Dessa "skal" skrivs med enklare språk

Seriöst? Electron är väl mindre C++ än vad all C++-program är assembler...

Ja, delar av Electron är skrivna i C++, ca 50 % av det projektet är C++ och de andra 50 % är TS. Det totalt ca 160k rader.

Hur gör det VS Code till ett C++-projekt när det själv består av ca 1,5 miljoner rader TS?

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Datavetare
Skrivet av klk:

Kan du utveckla hur det exemplet är relevant?
Jag tror många utvecklare som försöker dra nytta av alla kärnor hade jublat om de haft så enkla uppgifter

Vet du vad som ofta orsakar gråa hår för de som försöker parallellisera arbeten?

Ledtråd: Ta en så enkel sak som att läsa in CSV formaterad text, varför är den uppgiften svår att parallellisera?

Därför att det "enda" svåra i att effektivt utnyttja flera CPU-kärnor är att identifiera delarna som är oberoende, vad de behöver som privat indata och när man behöver återinföra det i "parent-flödet".

fib-exemplet är därför utmärkt att visa hur man just hanterar fan-out och fan-in. Allt övrigt handlar bara om data och är logiskt identiskt oavsett språk. Det som kan skilja sig rätt fundamentalt är hur man gör denna fan-out/fan-in, samt hur effektivt det är att göra detta.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Yoshman:

Seriöst? Electron är väl mindre C++ än vad all C++-program är assembler...

Ja, delar av Electron är skrivna i C++, ca 50 % av det projektet är C++ och de andra 50 % är TS. Det totalt ca 160k rader.

Hur gör det VS Code till ett C++-projekt när det själv består av ca 1,5 miljoner rader TS?

För att du inte klarar dig utan C++, det är kärnan och det är inte ovanligt att det är en mindre del (kodmässigt), Alla anpassningar mm måste ha denna snabba kärna

Permalänk
Datavetare
Skrivet av klk:

För att du inte klarar dig utan C++, det är kärnan och det är inte ovanligt att det är en mindre del. Alla anpassningar mm måste ha denna snabba kärna

Om man absolut vill skulle man enkelt kunna transpile:a all C++ som används till C, no need for C++ efter det.

Men varför? Det ändrar inte faktumet att väldigt få av applikationer som påbörjades senaste 10-15 åren använder längre C++, vilket är i direkt motsats till vad du påstår.

Som du resonerar är allt C, för alla relevanta OS är skrivna i C och går inte så bra att köra någon Windows, MacOS eller Linux applikation utan en OS-kärna.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Yoshman:

Därför att det "enda" svåra i att effektivt utnyttja flera CPU-kärnor är att identifiera delarna som är oberoende, vad de behöver som privat indata och när man behöver återinföra det i "parent-flödet".

Oberoende delar är inte svårt att parallellisera det är korrekt, så därför begriper jag inte ditt inlägg.
Det svåra är att parallellisera delar med beroenden. Klarar du det så klarar du så mycket mer

Permalänk
Medlem
Skrivet av Yoshman:

Men varför? Det ändrar inte faktumet att väldigt få av applikationer som påbörjades senaste 10-15 åren använder längre C++, vilket är i direkt motsats till vad du påstår.

C++ har aldrig använts i delar som kräver flexibilitet, det har aldrig varit så. Språket är inte byggt för det
Du flyttar de delar till andra format, metadata i olika varianter, ibland skriptspråk

Vad jag ibland kallar för deklarativ programmering. En annan typ av kodning

Permalänk
Datavetare
Skrivet av klk:

Oberoende delar är inte svårt att parallellisera det är korrekt, så därför begriper jag inte ditt inlägg.
Det svåra är att parallellisera delar med beroenden. Klarar du det så klarar du så mycket mer

Och hur har det något med C++ att göra?

Ja, man måste förstå beroenden. Ofta misslyckas den delen, vilket leder till data-race i alla språk förutom Rust (en väldigt unik egenskap är ju att data-race blir kompileringsfel i Rust).

När detta är gjort handlar det "bara" om att så effektivt som möjligt köra delarna och samla ihop resultaten.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Yoshman:

Och hur har det något med C++ att göra?

För här behöver du frihet

Skrivet av Yoshman:

Ja, man måste förstå beroenden. Ofta misslyckas den delen, vilket leder till data-race i alla språk förutom Rust (en väldigt unik egenskap är ju att data-race blir kompileringsfel i Rust).

Rust löser allt

Skrivet av Yoshman:

När detta är gjort handlar det "bara" om att så effektivt som möjligt köra delarna och samla ihop resultaten.

Titta på hur en processor fungerar, inte så stor skillnad. Du kan ibland "chansa" Om något i 9 fall av 10 ser ut på ett visst sätt så chansa, skulle det vara fel så kasta bort och gör om utan att parallellisera.
Det finns många trick för att få upp hastighet där data är beroende, det är inte lätt men det går.