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

Permalänk
Medlem
Skrivet av klk:

När du behöver prestanda och anstränger dig så för att få upp prestanda, då är det oftast väldigt viktigt.

Det finns oftast en mängd andra saker som kan göras som har betydligt större effekt på prestanda.
Gör man en profilering av ett välskrivet program vågar jag påstå att range-checks kommer väldigt långt ner på listan över sådant som tar tid (under förutsättning att det är en modern CPU med instruktionscache, branch-prediction, osv.)

Och den lilla, lilla kostnaden som finns för range-checks är väl värd det för tryggheten att veta att det inte finns några out-of-bounds buggar som kan ge säkerhetsproblem.

Citat:

Ber om ursäkt om det är repetering men har sagt tidigare i tråden.
C eller C++ väljs för att man inte har något annat alternativ. Det kan vara svårt att svälja om man älskar annat språk. Jag tror inte de som använder C eller C++ älskar språken utan de används för att de är bäst för det som skall göras.

Bara det att om C++ används så har man en hel hög med kompilatorer att välja på jämfört med en eller kanske två för andra språk.

Och det är svårt och diskutera lösningar mellan de som har sitt favoritspråk och de som måste lösa problem och välja verktyg efter det.

Att C i en del fall är det enda realistiska alternativet, det tror jag inte någon här egentligen ifrågasätter. Framför allt då för små inbyggda system där ibland den enda utvecklingsmiljön som finns är för C.

I de få fall där C++ är det bästa alternativet så är det aldrig för att språket i sig är bra (det är det inte), utan på grund av att projektet redan har en massa investerat i C++. (Stor mängd existerande C++ kod som är för mycket jobb att skriva om, eller utvecklare som bara kan C++ och där det är för dyrt att utbilda dem i något annat.)
Men för helt nya projekt vågar jag påstå att C++ aldrig är det bästa alternativet.

Och "en hel hög med kompilatorer"?
Vilka kompilatorer är dessa?
De C++ kompilatorer jag känner till som stöder moderna versioner av C++ och fungerar på PC är:
* Visual Studio
* GCC
* Clang/llvm

Tre stycken. Vilket inte är en hel hög.
Vilka har jag missat?

Permalänk
Medlem
Skrivet av Erik_T:

Det finns oftast en mängd andra saker som kan göras som har betydligt större effekt på prestanda.

Som vad då?

Skrivet av Erik_T:

Gör man en profilering av ett välskrivet program vågar jag påstå att range-checks kommer väldigt långt ner på listan över sådant som tar tid (under förutsättning att det är en modern CPU med instruktionscache, branch-prediction, osv.)

Det stämmer inte, det är ingen liten kostnad att hela tiden kontrollera så att man är inom gränser. Ofta är detta enkla operationer men det är massor. Låt säga att du skall gå igenom 1 000 000 värden och måste kontrollera varje värde. Det gör du inte utan då väljs en lösning så du slipper.

Jag tror de flesta C++ utvecklare tänker liknande som jag själv gör. Man tänker igenom kod och hur den används, är det kod som aldrig kan påverkas av en användare (användarfel och annan extern påverkan), då körs massor av kontroller i debug men i release plockas allt bort.

Personligen tycker jag det är extremt störande om man behöver nollställa pekare i språk vilket man inte behöver i C++, eller tilldela andra variabler för olika startvärden

Permalänk
Medlem
Skrivet av Erik_T:

* Visual Studio
* GCC
* Clang/llvm

Intel och MinGW är de jag vet om, vet inte om man skall räkna MinGW som en egen men skall man kompilera och efterlikna GCC på windows tror jag det är den som används.

C++ är extremt komplext och där är det inte så många men det är mer än i andra språk
C har du säkert över 100 olika kompilatorer

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Det krävs inte särskilt avancerad analys för att se att index-variablen u kommer gå från 0 till uSize. Om range check vore ett vanligt mönster i språket skulle det finnas optimeringar som letade efter just detta: loop med känd trip count och range checks i loop kroppen. Här kan kompilatorn välja att lägga ut två loopkroppar och välja vilken som körs baserat på loopens slutvärde:

Tittar du på hur optimeringar ser ut i C++ så brukar kompilatorn unrolla loopen för att kunna dra nytta av simd instruktioner.
Den lösning du föreslog har jag aldrig sett göras, det förutsätter att kompilatorn kan gissa att det alltid är många värden som skall kollas. Vanligt är att det inte är så många och då skulle en sådan lösning bli långsammare

Tänk också på att det normala när man skall visa exempel i sådana här diskussioner inte är realistiska. Vanlig kod är oftast mer komplex, innehåller mer värden och funktionalitet

Permalänk
Medlem
Skrivet av klk:

C har du säkert över 100 olika kompilatorer

Nöjer du dig med C90 så finns det ju en hel del kompilatorer.
Vill du ha en kompilator med fullt stöd för C99 eller senare versioner av C standarden så blir det betydligt färre att välja mellan.

Permalänk
Skrivet av klk:

Poängen är att om kompilatorn inte behöver göra kontroller så är den friare att göra om koden. Speciellt viktigt blir detta när kompilatorn inte vet om vad som finns i minnet.
I den kod du visar så skriver du så kompilatorn hela tiden vet vad som finns där, hur gör du när kompilatorn inte vet det?

Vad menar du när du skriver "inte vet vad som finns i minnet"? Pratar vi om typ eller innehåll? Jag gissar att du pratar om arena-allokatorfallet och att typen på accessen inte är den samma som minnesblocket som allokerades. Från runtime supportets sida ser jag ingen skillnad på om du allokerat en std::vector<float> och läser floats från den eller om du allokerat en minnesarea av godtycklig typ och gör läsningar av annan godtycklig typ från den. Det är minne (basadress och storlek) och accesser (effektiv adress och storlek) och antingen är den innanför eller utanför den allokerade arean.

Nu kan jag inte tillräckligt mycket om Rust för att uttala mig om kompilatorns frihet i Rust utan har fått förlita mig på ChatGPT. Tittar vi på C och C++ det strikt reglerat när sidoeffekter skall vara synliga i semantiken för den virtuella maskinen standarden beskriver. Det handlar dock om när själva tilldelningen görs, inte när uträkningen görs. Om vi tar en liten kodsnutt som

if (some_condition) x = c[k] + a[i] * b[j]; else y = d[l] - a[i] * b[j];

Under förutsättning att ingen av de ingående variablerna är deklarerade som volatile kan kompilatorn göra följande optimering (common subexpression):

tmp = a[i] * b[j]; if (some_condition) x = c[k] + tmp; else y = d[l] - tmp;

Denna omordning av accesserna sker helt bakom kulissen och är inte synlig för programmet i sig. Det enda programmet ser är att x eller y får ett nytt värde. Det vet inte att en stor del av uträkningen var gjord redan innan villkoret evaluerades.

Om ChatGPT har rätt, har Rust inga regler om i vilken ordning accesserna måste testas. Dvs, om både c[k] och b[j] är out-of-bounds är det fullt tillåtet att programmet får en panik orsakad b[j]-accessen. Detta ger kompilatorn exakt samma frihet att flytta om kod som i C++, så länge out-of-bounds-testet också flyttas och görs innan array-accessen. (Om man har ambitionen att ens språk skall kunna användas när prestanda är viktigt vore det korkat att sätta begränsningar som hindrar kompilatorns möjligheter att optimera koden. Eller hur?)

Skrivet av klk:

Tipsar om videon jag postade tidigare i tråden och som är en vanlig teknik som används i C och C++ kod (mer i C). Istället för att ha många små allokeringar skrivs kod så mycket kan läggas i ett enda block, kapslar in det och skriver egen kod för att sköta logiken. Troligen den mest vanliga tekniken för att få upp hastighet.

Tittade på videon. Blev inte frälst.

Om du bara skriver arena-allokator så vet vi alla vad du pratar om. Som jag uppfattat det kommer Rust inte att göra några range checks på objekten i arenan. Ur Rusts synvinkel räcker det att accesses sker inom minnesblocket du använder som arena.

Kompilatorn har samma möjligheter att optimera loopar över arrayer i arenan som för en float-vectors. Kan man räkna ut lägsta och högsta index räcker det att testa dessa. Är de inom arenan kan man köra en version av loopen helt utan range-tester.

Skrivet av klk:

Tittar du på hur optimeringar ser ut i C++ så brukar kompilatorn unrolla loopen för att kunna dra nytta av simd instruktioner.
...
Tänk också på att det normala när man skall visa exempel i sådana här diskussioner inte är realistiska. Vanlig kod är oftast mer komplex, innehåller mer värden och funktionalitet

Men hallå, @Yoshman tog DITT exempel från the Compiler Explorer, skrev om det i fungerande Rust och visade att koden kunde vektoriseras. Jag förklarade vad kompilatorn kunde göra för tricks för att kunna generera SIMD-instruktioner trots att det borde utföras range checks. Den andra loopen, den utan range checks, är likvärdig med loopen i din add-funktion. Kompilatorn borde kunna generera samma kod som du får ur C++-kompilatorn med unrolling och allt.

Skrivet av klk:

Den lösning du föreslog har jag aldrig sett göras, det förutsätter att kompilatorn kan gissa att det alltid är många värden som skall kollas. Vanligt är att det inte är så många och då skulle en sådan lösning bli långsammare

Vänligen ta den genererade koden för funktionen add från DITT exempel i the Compiler Explorer och be ChatGPT förklara vad GCC har gjort. GCC använder samma kodgenereringsstrategi som det exempel jag använde för att illustrera hur man kunde undvika range checks och därmed kunna generera SIMD-instruktioner.

if (kan denna loop optimeras) kör optimerad loop; else kör den ursprungliga loopen;

I C++-fallet måste GCC testa för aliasing. Om pResult pekar på en minnesarea som är mindre än 1 vektorvidd bort från p1 eller p2 då kan inte koden vektoriseras. Om vi har överlapp i source och destination (exempelvis &pResult[0] == &p1[2]) och vi läste 8 värden från p1 skulle p1[2] innehålla det "gamla" värdet och inte det som borde ha skrivits i till pResult[0] under den första iterationen. Om det är överlapp kan man inte köra SIMD-kod utan måste falla tillbaka på skalär kod (.L12).

Beträffande hastighet: den lösningen jag förslog kommer vara lika snabb eller snabbare (räkna antal körda tester) i alla fall utom då

  1. loopen inte körs över huvud taget, då skulle vi köra tester som vi inte gör i den ooptimerade koden, men vi kan även testa om uSize > 0 innan vi kör några av range testerna och slipper kostnaden för extra tester,

  2. någon av range checkerna fallerar, då kommer man ha gjort några range checker extra, men det vore fel att prioritera felfallen när vi optimerar.

Sedan kan du inte både gnälla på att det inte görs unrolling och sedan klaga på att min kod förutsätter att man skall köra många iterationer (vilket den inte gör). Unrolling har man nytta av först när man kör många iterationer. Du får bestämma dig vad du prioriterar

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Tittade på videon. Blev inte frälst.

Ok, men då får vi väl bara vänta in och se hur skitspråket C++ tas över av alla andra som nu är så mycket bättre och snabbare. Verkligheten får visa vem som har rätt

Why aren't C++ developers switching to Rust?

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Du får bestämma dig vad du prioriterar

Behöver jag verkligen det?

Vi diskuterar på nätet, att prata på ett sätt så att man utesluter alla möjliga luckor går inte, alla målar med bred pensel. Det går inte att konversera annars. Det trista är att detta är så vanligt bland programmerare. Programmerare i olika nivåer kan inte prata (jag vet, bara för att jag säger ordet "nivå" så kokar det hos en del).
C++ utvecklare har svårt att diskutera med Rust, java eller C# utvecklare (och det spelar ingen roll att gruppen som jagar mig här påstår något annat).

Ja det går att hitta enklare exempel där det går och få till det i enklare språk så de kan optimera, men de får ofta slå knut på sig själva för att göra det. Språken har hinder för den typen av kod. Det har inte C++

Den här typen av kod är inte rolig i C++ men det är en mardröm och få till det i andra språk

arguments& arguments::append(const char* pbszName, uint32_t uNameLength, argument_type uType, const_pointer pBuffer, unsigned int uLength) { assert(m_pbuffer->get_reference_count() <= 1); assert( uNameLength < 0x1000 ); // no change if two or more holds value and realistic name lenghts #ifndef NDEBUG enumCType eType_d = (enumCType)(uType & ~eTypeNumber_MASK); // get absolute variable type auto typename_d = gd::types::type_name_g( eType_d ); // readable name for type #endif // _DEBUG // ## calculate needed size to make sure internal buffer is large enough uint64_t uReserveLength = buffer_size(); // current buffer size /// ### [name type and nanme lenghth][name value]{value type and value buffer length]{native value length}[value data] = total byte count needed to store value uReserveLength += uNameLength + sizeof( uint32_t ); // name if any and length value for name uReserveLength += uLength + sizeof(uint32_t); // value length (and prefix value length for strings) uReserveLength += sizeof(uint32_t) * 2; // padding space to enable space for 32 bit alignment (name and value is aligned) uReserveLength = align32_g( uReserveLength ); // align // reserve data for name, length for name, name type, data type and data value // uReserveLength should be enough for -> [name type][name length][name text][value type]{native value length}[value data] reserve( uReserveLength ); auto uPosition = buffer_size(); assert( uPosition % 4 == 0 ); #ifndef NDEBUG auto uBegin_d = uPosition; // keep position to check total length for value in debug #endif // _DEBUG auto pdata_ = buffer_data(); uint32_t uTypeAndSize = (eType_ParameterName << 24) | uNameLength; *(uint32_t*)(pdata_ + uPosition) = uTypeAndSize; // set name type uPosition += sizeof( uint32_t ); // move past key type and length (stored in 32 bit value) memcpy(&pdata_[uPosition], pbszName, uNameLength); // copy name uNameLength = align32_g( uNameLength ); // align if needed uPosition += uNameLength; // add length for name assert( uPosition % 4 == 0 ); if( (uType & eValueLength) == 0 ) // if type doesn't have specified length flag then just copy data into buffer { uint32_t uValueLength = uLength; uLength = align32_g( uLength ); // align to 32 bit boundary uTypeAndSize = (uType << 24) | uLength; *(uint32_t*)(pdata_ + uPosition) = uTypeAndSize; // set type and size uPosition += sizeof( uint32_t ); memcpy(&pdata_[uPosition], pBuffer, uValueLength); // copy value data uPosition += uLength; // add aligned length buffer_set_size( uPosition ); assert(buffer_size() < buffer_buffer_size()); } else { uint32_t uValueLength = uLength; // value length in bytes (storage needed to hold data) uLength += sizeof( uint32_t ); // add value length to total value size uLength = align32_g( uLength ); // align to 32 bit boundary uTypeAndSize = (uType << 24) | uLength; // set value type and length in 32 bit value *(uint32_t*)(pdata_ + uPosition) = uTypeAndSize; // set type and size uPosition += sizeof( uint32_t ); // move past type and size uint32_t uCompleteType = gd::types::typenumber_to_type_g( uType & ~eType_MASK );// get the full type information from gd types to investigate the object length // ## fix size to the actual length for value, this is to improve the speed // generating value objects from data if(uCompleteType & gd::types::eTypeGroupString) { if(( uType & eTypeNumber_MASK ) == eTypeNumberWString) { assert( (uValueLength % 2) == 0 );// make sure unicode is correct uValueLength = uValueLength >> 1; // unicode string, length is cut in half } } *(uint32_t*)(pdata_ + uPosition) = uValueLength; memcpy(&pdata_[uPosition + sizeof( uint32_t )], pBuffer, uLength); // copy data uPosition += uLength; // move past data for value (length and data) buffer_set_size( uPosition ); assert(buffer_size() < buffer_buffer_size()); } #ifndef NDEBUG auto uValueSize_d = uPosition - uBegin_d; // total size needed for value in `arguments` object #endif // _DEBUG return *this; }

Dold text
Permalänk
Medlem
Skrivet av klk:

Behöver jag verkligen det?

Vi diskuterar på nätet, att prata på ett sätt så att man utesluter alla möjliga luckor går inte, alla målar med bred pensel. Det går inte att konversera annars. Det trista är att detta är så vanligt bland programmerare. Programmerare i olika nivåer kan inte prata (jag vet, bara för att jag säger ordet "nivå" så kokar det hos en del).
C++ utvecklare har svårt att diskutera med Rust, java eller C# utvecklare (och det spelar ingen roll att gruppen som jagar mig här påstår något annat).

Ja det går att hitta enklare exempel där det går och få till det i enklare språk så de kan optimera, men de får ofta slå knut på sig själva för att göra det. Språken har hinder för den typen av kod. Det har inte C++

Det är ändå rätt deprimerande läsning att du bara ignorerar allt han skriver och reagerar på en rad som i det stora hela är helt ointressant

Helt ärligt tror jag att du är ett troll.

Permalänk
Medlem
Skrivet av pine-orange:

Det är ändå rätt deprimerande läsning att du bara ignorerar allt han skriver och reagerar på en rad som i det stora hela är helt ointressant

Varför tror du det?
Jag har öst ut inlägg här och jag skulle kunna lägga ner någon timme eller två för att försöka förtydliga vad jag menar, tror du verkligen någon skulle lyssna (läsa) och ta till sig.

Det är en liten bubbla här som inte stämmer med en verklighet utanför (råa fakta talar ett mycket tydligt språk)

Permalänk
Skrivet av klk:

C++ utvecklare har svårt att diskutera med Rust, java eller C# utvecklare (och det spelar ingen roll att gruppen som jagar mig här påstår något annat).

Om jag inte varit tillräckligt tydlig med det så har jag sedan 1990 yrkesmässigt utvecklat i C och C++. Jag tillhör inte någon av de andra klickarna så du kan inte skylla våra meningsskiljaktigheter på det.

Vi må vara oense om vad som är en bra väg framåt för C++, men att jag synar dina orimliga uttalanden betyder inte att jag hatar C++. Snarare att jag inte hatar andra språk och känner ett behov att att svärta ner dem. Att jag debatterat med dig här på slutet handlar bara om att när du försöker motivera varför C++ är bättre än alla andra språk kommer det direkta felaktigheter och osanningar.

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Om jag inte varit tillräckligt tydlig med det så har jag sedan 1990 yrkesmässigt utvecklat i C och C++. Jag tillhör inte någon av de andra klickarna så du kan inte skylla våra meningsskiljaktigheter på det.

Vi må vara oense om vad som är en bra väg framåt för C++, men att jag synar dina orimliga uttalanden betyder inte att jag hatar C++. Snarare att jag inte hatar andra språk och känner ett behov att att svärta ner dem. Att jag debatterat med dig här på slutet handlar bara om att när du försöker motivera varför C++ är bättre än alla andra språk kommer det direkta felaktigheter och osanningar.

Vad tycker du om det som sägs här? Skulle samma text klara sig i denna tråden (finns gott om bra information där)
Why aren't C++ developers switching to Rust?

Och vi "nuddar" bara på ytan. Så många programmerare som skriver C++ går heller inte djupt utan använder språket för att de måste.

Vad jag vet finns inget språk som kan abstrahera så mycket som C++. Det går att skriva C++ kod så att python kodare skulle bli avundsjuka

Permalänk
Medlem
Skrivet av klk:

Vi diskuterar på nätet, att prata på ett sätt så att man utesluter alla möjliga luckor går inte, alla målar med bred pensel. Det går inte att konversera annars. Det trista är att detta är så vanligt bland programmerare. Programmerare i olika nivåer kan inte prata (jag vet, bara för att jag säger ordet "nivå" så kokar det hos en del).
C++ utvecklare har svårt att diskutera med Rust, java eller C# utvecklare (och det spelar ingen roll att gruppen som jagar mig här påstår något annat).

Jag är C-utvecklare och håller inte med dig. Som jag sa tidigare, jag tror inte att det är programmeringsspråken som gör att du inte kan diskutera med folk utan din syn på folk ihop med alla dina märkliga påstående som gör det svårt för dig att diskutera med någon.

Skrivet av klk:

Varför tror du det?
Jag har öst ut inlägg här och jag skulle kunna lägga ner någon timme eller två för att försöka förtydliga vad jag menar, tror du verkligen någon skulle lyssna (läsa) och ta till sig.

Det är en liten bubbla här som inte stämmer med en verklighet utanför (råa fakta talar ett mycket tydligt språk)

Jag tror att du är ett troll efter som du kastar ur dig helt bananas påståenden sedan synar någon som är väl påläst om ämnet ditt påstående och istället för att bemöta kritiken och slutföra en diskussion så drar du igång en ny. Du går t o m i ciklar som med sådan här smörja som inte går att tolka på annat sätt än trollande:

Skrivet av klk:

Vad jag vet finns inget språk som kan abstrahera så mycket som C++. Det går att skriva C++ kod så att python kodare skulle bli avundsjuka

Någon random weird fetish om att jämföra din religion med python ... och kasta ur sig saker utan exempel ...

Skrivet av klk:

Vad tycker du om det som sägs här? Skulle samma text klara sig i denna tråden (finns gott om bra information där)
Why aren't C++ developers switching to Rust?

Något random citat från quora som ingen har brytt sig om sedan 2010.

Permalänk
Medlem
Skrivet av orp:

Något random citat från quora som ingen har brytt sig om sedan 2010.

Precis
Skall jag ge dig 10 trådar till som ser nästan likadana ut

Fråga inte (orkar inte leta efter diskussiontrådar men det är vanligt)

Permalänk
Medlem
Skrivet av klk:

Precis
Skall jag ge dig 10 trådar till som ser nästan likadana ut

Fråga inte (orkar inte leta efter diskussiontrådar men det är vanligt)

Du verkar ha väldigt svårt att förstå att ingen försöker få dig att överge C++. Du gillar C++, stanna med C++!

Det jag vill att du slutar med är påstå att C++ är bättre än andra språk, framförallt i sammanhang som är felaktiga.

Folk kodar Python för att dom antingen gillar det eller så är deras kodbas redan skriven i det eller så är det snabbare att åstadkomma X i Python över andra språk. Dom väljer inte att skriva Python för att dom inte besitter förmågan att förstå datorer, komplexitet eller andra programmeringsspråk.

Det enda som har konstaterats är att C++ som programmeringsspråk inte kan garantera minnessäkerhet. Ingen har påstått att C++-utvecklare inte kan skriva kod som inte har minnesrelaterade problem.

Permalänk
Medlem
Skrivet av orp:

Det jag vill att du slutar med är påstå att C++ är bättre än andra språk, framförallt i sammanhang som är felaktiga.

Kalla det verktyg och det kommer jag inte göra och det beror på att det ÄR bättre, det klarar mer än andra språk.
Men allt har sitt pris och det är också svårare än andra språk.

Skall man göra samma typer av lösningar i andra språk så går det antingen inte alls (exempelvis har python lämnat walk over för allt som har med prestanda och göra). Språk med GC, där måste du installera en hel del för att programmen skall fungera.
Samma med javascript (node.js eller något annat som kan köra det).

Sist har vi då kvar de språk som kan bygga en egen fristående exe.

Också här kan C++ mer än de andra språken även om det här är jämnare. Men de andra språken som tävlar är oftast nyare och har inte i närheten av samma mängd kod att tillgå eller samma ekosystem.

Så faktamässigt är språket bättre om man räknar att två olika team som är jämbördiga och skall tävla om att få fram bäst produkt. Då kommer C++ har bättre förutsättningar för att vinna.

Men bara för att det är bättre skall kanske bara 5-10 % använda det. Lika lite som att jag kommer välja den mest avancerade videoredigeraren om jag vill knåpa ihop något snyggt kollage av semesterfilmer eller rita cad till 3d skrivaren, då väljs enklare cad. De som kan allt är för svåra och tar för lång tid att lära sig.

De svåra är till för personer som jobbar professionellt

Permalänk
Medlem
Skrivet av klk:

Det trista är att detta är så vanligt bland programmerare. Programmerare i olika nivåer kan inte prata (jag vet, bara för att jag säger ordet "nivå" så kokar det hos en del).

Så, det går inte att prata med med programmerare...

Skrivet av klk:

C++ utvecklare har svårt att diskutera med Rust, java eller C# utvecklare (och det spelar ingen roll att gruppen som jagar mig här påstår något annat).

...det spelar ingen roll vad andra säger, du vet att du har rätt?

I rest my case...

Skrivet av klk:

Kalla det verktyg och det kommer jag inte göra och det beror på att det ÄR bättre, det klarar mer än andra språk...

Jag behöver inte citera hela det här inlägget, men här framgår det med all önskvärd tydlighet vilka mindervärdeskomplex du har.

Det är ett endå långt "det språket jag har valt, och därmed jag som programmerar i det språket, är överlägset alla andra..."

Jag tror jag har frågat förut, ge oss något exempel på något du har utvecklat, någon produkt eller tjänst, så kan vi själva bedöma hur "bäst" du faktiskt är, inte bara genom att du säger att du är bäst.

Permalänk
Medlem
Skrivet av Xeonist:

Det är ett endå långt "det språket jag har valt, och därmed jag som programmerar i det språket, är överlägset alla andra..."

Korrekt.
Jämför med att tävla i exempelvis köra så snabbt som möjligt runt en formula 1 bana.
Sätter du dig i en volvo går det inte lika snabbt som om du kör en Formula 1 bil. Det är däremot säkrare

En formula 1 bil är inte konstruerad för att vara trygg, den är optimerad för att så snabbt som möjligt ta sig runt

Att vuxna människor har problem med någon säger att prestanda är viktigt för C++ programmerare, alltså jag vet inte hur jag skall tolka det. (en av egenskaperna som är viktigt för C/C++)

// Exempel på flexibel kod när det är lätt att manipulera minne class CDocument { ... public: /** \name GET/SET *///@{ gd::variant_view Get(const std::string_view& stringName) const { return m_arguments[stringName].as_variant_view(); } void Set(const std::string_view& stringName, const gd::variant_view& variantValue) { m_arguments.set(stringName, variantValue); } std::string_view GetName() const { return m_arguments["name"].as_string_view(); } void SetName(const std::string_view& stringName) { m_arguments.set("name", stringName); } std::string_view GetPath() const { return m_arguments["path"].as_string_view(); } void SetPath(const std::string_view& stringName) { m_arguments.set("path", stringName); } //@} public: gd::argument::shared::arguments m_arguments;///< document information (members) };

Dold text
Permalänk
Medlem
Skrivet av klk:

Korrekt.
Jämför med att tävla i exempelvis köra så snabbt som möjligt runt en formula 1 bana.
Sätter du dig i en volvo går det inte lika snabbt som om du kör en Formula 1 bil. Det är däremot säkrare

En formula 1 bil är inte konstruerad för att vara trygg, den är optimerad för att så snabbt som möjligt ta sig runt

Ja, fast det du föreslår är att man ska använda en Formel 1-bil i alla slags motorsport. Jag lovar att en Formel 1-bil inte kommer placera särskilt bra i exempelvis Dakar Desert Rally ...

Formel 1 bilar är designade för att vara trygga så att dom opt:at ut från säkerhet är falskt och utöver det är banorna designade för att vara trygga för att kompensera för säkerhet som inte finns i bilarna.

Skrivet av klk:

Att vuxna människor har problem med någon säger att prestanda är viktigt för C++ programmerare, alltså jag vet inte hur jag skall tolka det. (en av egenskaperna som är viktigt för C/C++)

Det är mer att vikten du lägger vid prestanda ihop med din dåliga exempel på prestanda låter som du:
1. Att du aldrig haft tidspress på jobb.
2. Att du är extremt oerfaren eftersom du inte kan välja rätt verktyg till rätt jobb.

Sedan pratar du om C++-utvecklare som kollektiv vilket får det till att låta ännu mer oseriöst. Det finns garanterat C++-utvecklare som gillar syntaxen som inte aktivt bryr sig om prestanda eftersom det finns värde att få ut features snabbt.

Permalänk
Medlem
Skrivet av orp:

Ja, fast det du föreslår är att man ska använda en Formel 1-bil i alla slags motorsport. Jag lovar att en Formel 1-bil inte kommer placera särskilt bra i exempelvis Dakar Desert Rally ...

Om du översätter detta till programmering så kan du ta ett exempel därifrån och varför. Varför C++ har sämre förutsättningar att klara sig

Permalänk
Medlem
Skrivet av klk:

Om du översätter detta till programmering så kan du ta ett exempel därifrån och varför. Varför C++ har sämre förutsättningar att klara sig

Det är rätt verktyg för rätt jobb. Varför tror du att det finns olika programmeringsspråk?
Jag som kodar C, varför ska jag bry mig om C++? Jag kan ju redan göra allt i C.

Permalänk
Medlem
Skrivet av orp:

Det är rätt verktyg för rätt jobb. Varför tror du att det finns olika programmeringsspråk?
Jag som kodar C, varför ska jag bry mig om C++? Jag kan ju redan göra allt i C.

Jag tror du använder C för att det finns regler som hindrar annat eller möjligen saknas kompetens för C++, kanske saknas det kompilatorer eller eventuellt är det annan kod man anpassar sig efter.

Det blir bra mycket mer kod för samma sak i C jämfört med C++ även om det går att göra samma sak.

Fast jag tänkte inte specifikt på C kontra C++, utan andra språk. I vilken situation är det där en fördel att välja något annat om man bortser från saker som kompetens och liknande som ligger utanför själva språket

Permalänk
Datavetare
Skrivet av klk:

Intel och MinGW är de jag vet om, vet inte om man skall räkna MinGW som en egen men skall man kompilera och efterlikna GCC på windows tror jag det är den som används.

C++ är extremt komplext och där är det inte så många men det är mer än i andra språk
C har du säkert över 100 olika kompilatorer

Som jag förstått det lade Intel i praktiken ned sin egen kompilator 2021, istället jobbar man med att få in motsvarande optimeringar i LLVM.
https://www.phoronix.com/news/Intel-LLVM-Adoption-C-CPP

MinGW är en Windows port av GCC. "Vanliga" GCC är bara designad för *NIX.

Men det finns ett par till C++ kompilatorer till. Den jag känner bäst till är DIAB som länge var den bästa kompilatorn för PowerPC, idag är fokus där primärt på områden för certifiering och det primärt för ARM64 och x64.

Skrivet av klk:

Den här typen av kod är inte rolig i C++ men det är en mardröm och få till det i andra språk

arguments& arguments::append(const char* pbszName, uint32_t uNameLength, argument_type uType, const_pointer pBuffer, unsigned int uLength) { assert(m_pbuffer->get_reference_count() <= 1); assert( uNameLength < 0x1000 ); // no change if two or more holds value and realistic name lenghts #ifndef NDEBUG enumCType eType_d = (enumCType)(uType & ~eTypeNumber_MASK); // get absolute variable type auto typename_d = gd::types::type_name_g( eType_d ); // readable name for type #endif // _DEBUG // ## calculate needed size to make sure internal buffer is large enough uint64_t uReserveLength = buffer_size(); // current buffer size /// ### [name type and nanme lenghth][name value]{value type and value buffer length]{native value length}[value data] = total byte count needed to store value uReserveLength += uNameLength + sizeof( uint32_t ); // name if any and length value for name uReserveLength += uLength + sizeof(uint32_t); // value length (and prefix value length for strings) uReserveLength += sizeof(uint32_t) * 2; // padding space to enable space for 32 bit alignment (name and value is aligned) uReserveLength = align32_g( uReserveLength ); // align // reserve data for name, length for name, name type, data type and data value // uReserveLength should be enough for -> [name type][name length][name text][value type]{native value length}[value data] reserve( uReserveLength ); auto uPosition = buffer_size(); assert( uPosition % 4 == 0 ); #ifndef NDEBUG auto uBegin_d = uPosition; // keep position to check total length for value in debug #endif // _DEBUG auto pdata_ = buffer_data(); uint32_t uTypeAndSize = (eType_ParameterName << 24) | uNameLength; *(uint32_t*)(pdata_ + uPosition) = uTypeAndSize; // set name type uPosition += sizeof( uint32_t ); // move past key type and length (stored in 32 bit value) memcpy(&pdata_[uPosition], pbszName, uNameLength); // copy name uNameLength = align32_g( uNameLength ); // align if needed uPosition += uNameLength; // add length for name assert( uPosition % 4 == 0 ); if( (uType & eValueLength) == 0 ) // if type doesn't have specified length flag then just copy data into buffer { uint32_t uValueLength = uLength; uLength = align32_g( uLength ); // align to 32 bit boundary uTypeAndSize = (uType << 24) | uLength; *(uint32_t*)(pdata_ + uPosition) = uTypeAndSize; // set type and size uPosition += sizeof( uint32_t ); memcpy(&pdata_[uPosition], pBuffer, uValueLength); // copy value data uPosition += uLength; // add aligned length buffer_set_size( uPosition ); assert(buffer_size() < buffer_buffer_size()); } else { uint32_t uValueLength = uLength; // value length in bytes (storage needed to hold data) uLength += sizeof( uint32_t ); // add value length to total value size uLength = align32_g( uLength ); // align to 32 bit boundary uTypeAndSize = (uType << 24) | uLength; // set value type and length in 32 bit value *(uint32_t*)(pdata_ + uPosition) = uTypeAndSize; // set type and size uPosition += sizeof( uint32_t ); // move past type and size uint32_t uCompleteType = gd::types::typenumber_to_type_g( uType & ~eType_MASK );// get the full type information from gd types to investigate the object length // ## fix size to the actual length for value, this is to improve the speed // generating value objects from data if(uCompleteType & gd::types::eTypeGroupString) { if(( uType & eTypeNumber_MASK ) == eTypeNumberWString) { assert( (uValueLength % 2) == 0 );// make sure unicode is correct uValueLength = uValueLength >> 1; // unicode string, length is cut in half } } *(uint32_t*)(pdata_ + uPosition) = uValueLength; memcpy(&pdata_[uPosition + sizeof( uint32_t )], pBuffer, uLength); // copy data uPosition += uLength; // move past data for value (length and data) buffer_set_size( uPosition ); assert(buffer_size() < buffer_buffer_size()); } #ifndef NDEBUG auto uValueSize_d = uPosition - uBegin_d; // total size needed for value in `arguments` object #endif // _DEBUG return *this; }

Dold text

Du har postat ett i stort sätt samma exempel här
#20783543

finns inget i någon av de två exemplen som inte kan göras rätt mycket exakt lika effektivt i Rust, Go, C#, m.fl. Du fick ett exempel i Rust här
#20783605

Skrivet av klk:

Korrekt.
Jämför med att tävla i exempelvis köra så snabbt som möjligt runt en formula 1 bana.
Sätter du dig i en volvo går det inte lika snabbt som om du kör en Formula 1 bil. Det är däremot säkrare

En formula 1 bil är inte konstruerad för att vara trygg, den är optimerad för att så snabbt som möjligt ta sig runt

Förutom att billiknelser sällan blir perfekta har du här fått flera konkreta beskrivningar varför det inte alls är säkert att C++ ger snabbast/mest effektiva kod längre (ignorerat att man handhackar i assembler, men då är det inte C++ längre).

C++ största värde är dess ålder kombinerat med att det länge, ihop med C, rätt mycket var det enda språk med bra stöd för att skriva högpresterande programvara om man ville slippa sitta med assembler. Mycket vatten har runnit under broarna och väldigt mycket har förändrats rätt fundamentalt sedan C++ introduktion i mitten av 80-talet och dess standardisering med början på 90-talet.

Vissa designval i C++ kan inte ändras med mindre än att paja bakåtkompatibilitet. Vissa av dessa val gör att moderna kompilatorer kan i vissa lägen göra fler optimeringar i mer moderna språk. Att minimera antalet CPU-instruktioner är inte heller alls lika viktigt idag som på 80/90-talet.

Idag kan man nästan tänka "alla instruktioner tar 0 cykler, förutom när man missar cache och måste gå mot RAM då det tar 100-tals cykler att köra en instruktion". Och det är när man ändå fortfarande kör sina tunga beräkningar på CPU, vi ser allt fler av de riktigt "compute-bound" lasterna allt mer hanteras av specialkretsar som GPU, NPU, etc. Ett väldigt målande exempel på det är machinelearning där det inte spelar någon roll att man sitter i Python, det är ändå snabbare än vad någon skulle få ihop med ett CPU-only C++ bibliotek då detta är något som är långt snabbare på GPU så fort problemet blir "tillräckligt stort".

C++ kanske är en 80-tals F1 bil, men det finns idag touring bilar där man får säkerheten av ett tak, en större cockpit men som ändå kan köra minst lika snabbt, i.e. Rust
Sen finns ju andra fall som Go, ISPC, etc om banan inte råkar vara en F1-bana utan kanske en street-bana där F1 bilen kommer få problem vid första större ojämnhet i vägen...

Skrivet av klk:

Att vuxna människor har problem med någon säger att prestanda är viktigt för C++ programmerare, alltså jag vet inte hur jag skall tolka det. (en av egenskaperna som är viktigt för C/C++)

Fast är det någon som säger det i denna tråd?

Har själv använt C++ väldigt mycket genom åren. Senaste ~5 åren har det i praktiken bara innefattat legacy-fall, i.e. jag har jobbat med C++ "för jag har väldigt mycket erfarenhet av C++, så tenderar bli inslängd i sådana projekt". Men ser inte längre någon anledning alls att idag välja C++ för ett green-field eller ens brown-field projekt då det finns bättre alternativ för alla use-case jag kan tänka mig.

Orsakerna att använda C++ idag är innefattar absolut "prestanda är viktigt", majoriteten av legacy-projekt som använder C++ gör det väldigt ofta p.g.a. detta. Men har man förmånen att starta från scratch idag finns andra alternativ som är enklare, som i praktiken kommer ge minst lika bra prestanda (ta Go som p.g.a. av sin unika runtime-miljö är långt enklare att hantera storskaliga I/O-tunga jobb jämfört med C++, bästa C++ kan göra är kopiera detta så gott det går för att ge legacy-kod en liknande möjlighet även om den är gisigare/krångligare och inte nödvändigtvis lika effektiv).

Och idag är det viktigare att utnyttja saker som parallellism (beroende på problem så kan det vara multicore och/eller SIMD) och i allt större utsträckning olika former av acceleratorer. Se på t.ex. Blender och PyTorch, spelar ingen roll hur mycket C++-optimeringar du stoppar in även med den snabbaste CPU du hittar, det kommer ändå vara heltalsfaktorer snabbare på en GPU även om CPU-delen av programmet körs i Python!

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:

finns inget i någon av de två exemplen som inte kan göras rätt mycket exakt lika effektivt i Rust, Go, C#, m.fl. Du fick ett exempel i Rust här

Den arguments klassen ligger på c.a. 5000 rader med kommentarer, den kan en hel del, det är inte samma

Skrivet av Yoshman:

Vissa designval i C++ kan inte ändras med mindre än att paja bakåtkompatibilitet.

C++ är inte perfekt, misstag har gjorts och har själv några önskemål som borde vara ganska enkla att lägga till men man kan inte få allt här i världen. Men, har inte sett något annat språk med mindre problem. Tvärtom så har de mycket mer

Skrivet av Yoshman:

Fast är det någon som säger det i denna tråd?

Det är tydligen känsligt att berätta att C++ klarar att göra allt bättre än andra språk

Permalänk
Datavetare
Skrivet av klk:

Den arguments klassen ligger på c.a. 5000 rader med kommentarer, den kan en hel del, det är inte samma

Och ändå har då så här långt inte lyckats plocka ut ett enda exempel som inte kan göras precis lika effektivt i t.ex. Rust.

Du har 5000 rader att välja på, om du inte kan plocka ut ett enda exempel kanske, bara kanske, det finns ett hyfsat enkelt svar: inget här är unikt för C++ m.h.p prestanda?

Det tråden handlar om är att en unik egenskap hos C++ (och C) är hur vanlig vissa typer av minnes-relaterade buggar är. Samma här, det kanske, bara kanske, är så att vi lärt oss något genom åren och använt den erfarenheten att skapa alternativ som är lika snabba men som inte har problemen?

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:

Det blir bra mycket mer kod för samma sak i C jämfört med C++ även om det går att göra samma sak.

Här har du anledningen till "rätt verktyg till rätt jobb".

Det blir med kod om vi skulle skriva allt i C++ eller C för den delen ... Har jag några problem med att skriva C? Nope.
Om vi skulle behöva ett API som interface till en databas, tror du att min arbetsgivare vill betala för 4 timmar att få det löst i Python eller en vecka och få en lösning i C?

Jag tror att min arbetsgivare vill betala för 4 timmar och om prestanda skulle vara ett problem så löser vi det i ett senare skede med en drop-in replacement.

Personligen skriver jag gärna C och undviker C++, jag har ingen aning om vad C++ löser under huven som har lett till problem de få gångerna jag har försökt. Jag hanterar helst mitt minne helt själv utan C med stödhjul(C++).

Permalänk
Medlem
Skrivet av Yoshman:

Och ändå har då så här långt inte lyckats plocka ut ett enda exempel som inte kan göras precis lika effektivt i t.ex. Rust.

Du har 5000 rader att välja på, om du inte kan plocka ut ett enda exempel kanske, bara kanske, det finns ett hyfsat enkelt svar: inget här är unikt för C++ m.h.p prestanda?

Det är för att du inte nappar på arkitektur. Du märker inte när du läser koden

Här har du ett pattern som sällan används av andra vilket jag tycker är märklighet men det är extremt skalbart och effektivt
The command dispatcher pattern (finns några olika varianter på samma sak)

Permalänk
Medlem
Skrivet av orp:

Det blir med kod om vi skulle skriva allt i C++ eller C för den delen ... Har jag några problem med att skriva C? Nope.
Om vi skulle behöva ett API som interface till en databas, tror du att min arbetsgivare vill betala för 4 timmar att få det löst i Python eller en vecka och få en lösning i C?

Har gjort några databaslösningar och låt säga att du har en databas på 300 tabeller. Hur gör du för att hantera det i python och det kanske bara är 3-4 utvecklare som skall göra ett system, ni vet inte exakt så flexibilitet måste till så man snabbt kan ändra

Permalänk
Medlem
Skrivet av klk:

Har gjort några databaslösningar och låt säga att du har en databas på 300 tabeller. Hur gör du för att hantera det i python och det kanske bara är 3-4 utvecklare som skall göra ett system, ni vet inte exakt så flexibilitet måste till så man snabbt kan ändra

Det är extremt löst specat.

Jag hade slängt upp en lösning med python-eve(konfigurerbart REST API) till en postgres-databas sedan eftersom API är stateless så kan jag slänga in det i ett kluster och skala både APIet och databas-delarna. Med en sådan lösning kan du hantera API-förändringar genom att ändra en konfig och starta om tjänsten.

Permalänk
Medlem
Skrivet av orp:

Det är extremt löst specat.

Jag hade slängt upp en lösning med python-eve(konfigurerbart REST API) till en postgres-databas sedan eftersom API är stateless så kan jag slänga in det i ett kluster och skala både APIet och databas-delarna. Med en sådan lösning kan du hantera API-förändringar genom att ändra en konfig och starta om tjänsten.

Ja det är löst specat men det är så mycket att du omöjligt kan lösa det med så få personer utan att få en salig röra. Du måste välja andra vägar än vad som är "normalt". Låt säga att dessa 3-4 utvecklare har ett år på sig.

När du säger rest-api. tänker du CRUD eller hur skall så få personer hålla reda på allt? 300 tabeller blir extremt många api'n