Deklarieren von Variablen hinter der Schleife oder innerhalb der Schleife? - Seite 11

 
Vict:

Ich habe nachgeschaut, es stellt sich heraus, dass kein https://en.cppreference.com/w/cpp/compiler_support Compiler die Module fertiggestellt hat, also gibt es nichts zu sehen.

Die Module können trotzdem über clang verwendet werden

// module
export module M;
export int f(int x) {
    return 2 + x;
}

// main.cc
import M;
int main() {
        for(int i = 0;  i < 1000000;  ++ i)
                f(5);
}

Bei der Kompilierung mit Optimierung wurde die Schleife überhaupt nicht ausgeführt (d.h. die Optimierung erfolgt zwischen: Übersetzungseinheit + halbverbundenen Modulen, anstatt nur einer Übersetzungseinheit wie zuvor). Ohne LTO. std c++ kandidiert, um vollständig auf Module umzusteigen, imho, und es wird keine Fragen geben: "warum so langsam auf diesem künstlichen Beispiel mit nackter Schleife".

 
Alexey Navoykov:

Es scheint also herausgefunden zu haben, dass es auch in diesem Fall jedes Mal Speicher zuweist und löscht:


Übrigens kann es sein, dass ich beim letzten Mal falsche Ergebnisse angegeben habe. Wahrscheinlich war es im x86-Modus. Jetzt teste ich im x64-Modus und die Ergebnisse von C++ sind viel besser:

1) ~ 2000 msec

2) ~ 200 ms (das ist 3 Mal schneller).

Obwohl ich auch Studio auf die neueste Version aktualisiert habe, muss sich das auch ausgewirkt haben, denn selbst x86 ist jetzt schneller als bei früheren Tests.

Nun, jetzt ist C++ nicht so schändlich verliert zu Sharp. nur um 3 mal etwa )

Hmm, also gibt es keinen Garbage Collector, wie lautet die Definitionsfrage?

Ich spreche nicht von der Geschwindigkeit, sondern vom Speicher.
 
Alexey Navoykov , es stellt sich heraus, dass constexpr string und vector in c++20 gezogen wurden. D.h. alle unsere Tests benötigen keine einzige Anweisung, um eine Zeichenkette zu bedienen, z.B. Speicher zuzuweisen, etc. (natürlich nur, wenn die Symbole nicht aus früheren Zeiten stammen). Cool.
 
Vict:
Alexey Navoykov , es stellt sich heraus, dass constexpr string und vector in C++20 gezogen wurden. D.h. alle diese Tests benötigen keine einzige Anweisung für die Pflege der Zeichenketten, z.B. für die Speicherzuweisung usw. (natürlich nur, wenn die Symbole nicht aus früheren Zeiten stammen). Cool.

Ist es also erforderlich, alles explizit als constexpr zu markieren, oder wird es automatisch erkannt?

Meines Erachtens liegt das Problem nicht in der Norm, sondern im Compiler. Hindert ihn etwas daran, unnötiges Zeug herauszuschneiden? Besonders seltsam ist, dass der Sharp-Compiler normal optimiert, während die Plus-Version vonMicrosoft versagt. Obwohl es scheint, dass sie eine gemeinsame Basis haben sollten (in Bezug auf die Optimierung solcher Konstruktionen)

 
Alexey Navoykov:

Ist es notwendig, alles explizit als constexpr zu markieren oder wird es automatisch erkannt?

Die std ist automatisch, es reicht, dass die Zeichenfolge die Zeichenfolgen erhält, die zur Kompilierungszeit bekannt sind. Alle Operationen (Suchen, Ersetzen, ...) mit dieser Zeichenkette werden zur Kompilierzeit die gleichen sein (ich vermute, dass sharp und mcl unsere Beispiele auch zur Kompilierzeit gezählt haben). Geplant ist, dass alle Container konstepxr werden. D.h. es hängt nicht mehr von der Laune des Compilers ab, sondern garantiert durch den Standard, dass wir z.B. Template-Parameter über String-Parsing berechnen können. Hier ist, was interessant ist - es stellt sich heraus, dass new/delete jetzt auch constexpr (für constexpr Typen)?

Wie es mir scheint, liegt das Problem nicht im Standard, sondern im Compiler. Hindert ihn etwas daran, unnötiges Zeug herauszuschneiden? Besonders seltsam ist, dass der Sharp-Compiler normal optimiert und die Plus-Version von Microsoft versagt, obwohl es scheint, dass sie eine gemeinsame Basis haben müssen (in Bezug auf die Optimierung solcher Konstrukte)

Plus hat einen Nachteil in Bezug auf die Optimierungsmöglichkeiten - es ist nur innerhalb einer Übersetzungseinheit (wenn wir nicht LTO verwenden). Natürlich können Sie die ganze std auf Header-Dateien zu tun, aber sie tun es nicht (wegen der Kompilierzeit ?). Sharp mit Modulen ist in dieser Hinsicht weiter fortgeschritten. Aber c++20 wird auch dies bald mit der Einführung von Modulen beheben. Außerdem ist geplant, std dorthin zu verlagern (zuerst werden sie die Module debuggen, dann werden sie sie schreiben). Aber VS scheint bereits std auf Module getan haben, können Sie es versuchen (links den Link oben).

Aber ich bestehe immer noch darauf, dass es besser ist, nach der Schleife zu deklarieren (wenn es sich nicht um einen grundlegenden Typ handelt).

 
Alexey Navoykov:

Ich habe beschlossen, es aus Neugier auch in C# zu testen, und die Ergebnisse sind nicht nur fast gleich schnell, sondern funktionieren auch viel schneller als in C++.

Ergebnisse:

Summe: 894782460, Zeit: 69 ms.

Summe: 894782460, Zeit: 56 ms

Und hier ist ein Analogon in C++:

Summe: 894782460, Zeit: 2947 ms

Summe: 894782460, Zeit: 684 ms

Ich teste es in VS 2019,alle Optimierungen sind aktiviert .

Scheiß auf ein solches C++-Programm).

p.s. Die Ergebnisse in C# variieren angenehm von Test zu Test, aber im Durchschnitt sind beide Varianten gleich schnell.

Hinweis: In sharpe ist string der Basistyp, in pluses ist es eine in plus geschriebene Klasse. Bei der Sharpe-Variante erfolgt die Zuordnung der Zeichenketten einmal, bei der Plus-Variante 10e6-mal. Letztendlich sind Pluspunkte schneller, aber man muss beim Schreiben von Code klug vorgehen und nicht wie die Inder bei Boeing einen Buckel machen.
 
SeriousRacoon:
Hinweis: In sharpe ist string der Basistyp, in pluses ist es eine in plus geschriebene Klasse. Bei der Sharpe-Variante erfolgt die Zuordnung der Zeichenketten einmal, bei der Plus-Variante 10e6-mal. Die Vorteile sind letztendlich schneller, aber man muss beim Schreiben von Code sein Gehirn einschalten, anstatt einen Buckel zu machen wie die Indianer in Boeing.
Nein, darum geht es nicht. Ich habe einfach vergessen, dass es eine Klasse String gibt und dass es die Referenz ist, die zugewiesen wird, nicht das Objekt selbst. Der Vergleich ist also in dieser Form falsch
 

Übrigens, wo wir gerade von Optimierung sprechen. Möchten Sie, dass der Compiler hier etwas optimiert?

mutex mtx;

void thread_0() {
        while (true) {
                do_task_0();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_1();
                }
                do_task_2();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_3();
                }
                do_task_4();
        {
}
void thread_1() {
        while (true) {
                do_task_5();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_6();
                }
                do_task_7();
                {
                        lock_guard<mutex> lck{mtx};
                        do_task_8();
                }
                do_task_9();
        {
}
 
Alexey Navoykov:
Nein, da geht es um etwas ganz anderes. Ich habe nur vergessen, dass string dort eine Klasse ist und es eine Referenz ist, die zugewiesen wird, nicht das Objekt selbst. Der Vergleich ist also in dieser Form falsch
Wo wird die Referenz (der Zeiger) zugewiesen? In der Plusklasse string? Was meinen Sie damit, dass die Pufferauswahl und das Kopieren dort stattfinden.
 
SeriousRacoon:
Wo wird der Verweis (Zeiger) zugewiesen? In der Plusklasse string? Was meinen Sie, es ist Puffer Auswahl und Kopieren.

er spricht über scharfe