Déclarer les variables derrière la boucle ou à l'intérieur de la boucle ? - page 11

 
Vict:

J'ai vérifié, il s'avère qu'aucun compilateur https://en.cppreference.com/w/cpp/compiler_support n'a terminé les modules, donc il n'y a rien à voir.

J'ai quand même réussi à utiliser les modules via clang

// 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);
}

Compilé avec optimisation, la boucle n'a pas été exécutée du tout (c'est-à-dire que l'optimisation est faite parmi : unité de traduction + modules demi-connectés, au lieu d'une seule unité de traduction comme avant). Sans aucun LTO. le candidat std c++ se déplace entièrement vers les modules, imho, et il n'y aura pas de questions : "pourquoi si lent sur cet exemple artificiel avec boucle nue".

 
Alexey Navoykov:

Il semble donc avoir compris qu'il alloue et supprime la mémoire à chaque fois, même dans ce cas :


Au fait, j'ai peut-être donné des résultats erronés la dernière fois. C'était probablement en mode x86. Je teste maintenant en mode x64 et les résultats par C++ sont bien meilleurs :

1) ~ 2000 msec

2) ~ 200 ms (c'est 3 fois plus rapide).

Bien que j'aie également mis à jour Studio à la dernière version, cela a dû l'influencer aussi puisque même x86 est plus rapide maintenant que les tests précédents.

Eh bien, maintenant C++ n'est pas si honteusement perdu par Sharp. seulement par 3 fois environ )

Hmm, donc il n'y a pas de ramasseur de déchets, quelle est la question de définition ?

Je ne parle pas de vitesse, je parle de mémoire.
 
Alexey Navoykov , il s'avère que les constexpr string et vector ont été glissés dans c++20. C'est-à-dire que tous nos tests ne prendront pas une seule instruction pour servir une chaîne, par exemple allouer de la mémoire, etc. (enfin, si les symboles ne proviennent pas de l'époque ancienne, bien sûr). Cool.
 
Vict:
Alexey Navoykov , il s'avère que constexpr string et vector ont été glissés dans C++20. C'est-à-dire que tous ces tests ne prendront pas une seule instruction pour la maintenance de la chaîne, par exemple l'allocation de mémoire, etc. (enfin, si les symboles ne proviennent pas de l'époque ancienne, bien sûr). Cool.

Est-ce qu'il faut marquer tout explicitement comme constexpr, ou est-ce qu'il le détectera automatiquement ?

D'après moi, le problème n'est pas dans la norme, mais dans le compilateur. Quelque chose l'empêche-t-il de supprimer les éléments inutiles maintenant ? Il est particulièrement étrange que le compilateur Sharp optimise normalement, alors que la version plus du mêmeMicrosoft échoue. Bien qu'il semble qu'ils devraient avoir une base commune (en termes d'optimisation de ces constructions).

 
Alexey Navoykov:

Est-il nécessaire de marquer explicitement tout comme constexpr ou le logiciel le détectera automatiquement ?

La std est automatique, il suffit que la chaîne obtienne les chaînes connues au moment de la compilation. Toutes les opérations (recherche, remplacement, ...) avec cette chaîne seront les mêmes au moment de la compilation (je soupçonne que sharp et mcl ont compté nos exemples au moment de la compilation aussi). Le plan est de rendre tous les conteneurs constepxr. C'est-à-dire qu'il ne dépend plus de l'humeur du compilateur, mais garanti par la norme, nous pouvons calculer le paramètre du modèle via l'analyse syntaxique des chaînes, par exemple. Voici ce qui est intéressant : il s'avère que new/delete sont maintenant aussi constexpr (pour les types constexpr) ?

Il me semble que le problème n'est pas dans la norme mais dans le compilateur. Quelque chose l'empêche-t-il de supprimer les choses inutiles ? Il est particulièrement étrange que le compilateur Sharp optimise normalement et que la version plus du même Microsoft échoue, bien qu'il semble qu'ils doivent avoir une base commune (en termes d'optimisation de ces constructions).

Plus présente un inconvénient en termes de possibilités d'optimisation : il ne s'agit que d'une unité de traduction (si nous n'utilisons pas de LTO). Bien sûr, vous pouvez faire tout le std sur les fichiers d'en-tête, mais ils ne le font pas (à cause du temps de compilation ?). Sharp avec des modules est plus avancé à cet égard. Mais c++20 va aussi corriger cela bientôt avec l'arrivée des modules. Il est également prévu d'y déplacer std (d'abord ils débogueront les modules et ensuite ils les écriront). Mais VS semble avoir déjà fait std sur les modules, vous pouvez l'essayer (à gauche du lien ci-dessus).

Mais je persiste à dire qu'il est préférable de déclarer après la boucle (enfin, si ce n'est pas un type fondamental).

 
Alexey Navoykov:

J'ai décidé de le tester également en C# par curiosité. Non seulement les résultats sont presque les mêmes en termes de vitesse, mais ils fonctionnent également beaucoup plus rapidement qu'en C++.

Résultats :

Somme : 894782460, Temps : 69 ms.

Somme : 894782460, Temps : 56 ms

Et voici un analogue en C++ :

Somme : 894782460, Temps : 2947 ms

Somme : 894782460, Temps : 684 ms

Je le teste dans VS 2019,toutes les optimisations sont activées .

Au diable un tel C++.)

p.s. Les résultats en C# varient agréablement d'un test à l'autre, mais en moyenne les deux variantes sont aussi rapides l'une que l'autre.

Astuce : dans sharpe string est le type de base, dans pluses c'est une classe écrite en pluses. Dans la variante Sharpe, l'affectation des chaînes est effectuée une fois, dans les plus - 10e6 fois. En fin de compte, les plus sont plus rapides, mais vous devez être intelligent lorsque vous écrivez du code, et non pas faire une bosse comme les Indiens de Boeing.
 
SeriousRacoon:
Astuce : dans sharpe string est le type de base, dans pluses c'est une classe écrite en pluses. Dans la variante Sharpe, l'affectation des chaînes est effectuée une fois, dans les plus - 10e6 fois. Les plus sont plus rapides au final, mais il faut faire appel à son cerveau pour écrire du code au lieu de faire un bossu comme les Indiens de Boeing.
Non, ce n'est pas ce dont il s'agit. J'ai simplement oublié qu'il existe une classe de chaîne de caractères et que c'est la référence qui est assignée, et non l'objet lui-même. Ainsi, la comparaison est incorrecte sous cette forme
 

Au fait, en parlant d'optimisation. Voulez-vous que le compilateur optimise quelque chose ici ?

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:
Non, le point est tout à fait différent là. J'ai juste oublié que la chaîne de caractères est une classe et que c'est une référence qui est assignée, pas l'objet lui-même.
Où est attribuée la référence (pointeur) ? Dans la classe plus string ? Que voulez-vous dire, la sélection et la copie du tampon ont lieu à cet endroit.
 
SeriousRacoon:
Où la référence (pointeur) est-elle assignée ? Dans la chaîne de la classe plus ? Que voulez-vous dire, c'est la sélection et la copie du tampon.

qu'il parle d'aiguës