Programmation asynchrone et multithread dans MQL - page 34

 
Andrei Novichkov:
Mais je me demande s'il y a des tâches qui nécessitent vraiment le thread pooling ? Pas simplement - créer un fil, l'oublier et attendre qu'il s'épuise, mais exactement un pool, comme le décrit Williams ? Si je ne me trompe pas, il s'agit là d'un exemple de distributeur automatique de billets - quelle tâche pourrait justifier un tel judo miraculeux ? Je ne peux pas encore penser à une telle tâche. Et pourquoi ne regardez-vous pas vraiment ThreadPool où tout est déjà fait, il y a de la documentation et des exemples.

Pour être honnête, jusqu'à présent je n'ai pas vu beaucoup de sens entrestd::async et le pool de threads, sauf questd::async crée et supprime automatiquement un thread pour la tâche en cours.
Et pour utiliser le pooling de threads, vous devez connaître à l'avance le nombre de threads utilisés dans le programme, et définir explicitement ce nombre pour le pool.
Il s'avère que le thread pooling est statique en termes de nombre de threads, bien que cela puisse ne pas être le cas, je ne peux pas l'affirmer.
Mais dans le livre de Williams, il dit que le thread pooling est recommandé lorsqu'il y a de très nombreuses tâches à exécuter dans std::thread.
Et peut-être que cela ne s'applique pas àstd::async, je n'en ai pas encore bien saisi le sens.
Et l'asynchronie est très demandée dans les solutions de mise en réseau, et les stratégies multi-symboles, et pour les calculs chargés est également utile.
Mais avecstd::async et std::promise dans la norme, je pense qu'il n'est pas nécessaire de créer un pool de threads.

 

Il y a aussi une question sur la mise en place d'un projet pour dll.
Comment se débarrasser des fonctions inutilisées, qui sont automatiquement tirées dans la dépendance de la dll par les compilateurs ?

J'ai déjà essayé différents environnements de développement, et chacun d'eux tire sa propre fonction inutilisée.
MSVS_2017 crée même ses propres dépendances d'exécution, dont je ne peux pas me débarrasser.
C'est pourquoi j'ai essayé différents IDE, mais ils utilisent également des fonctions inutilisées.
Comment s'en débarrasser ?

 
Roman:

Pour être honnête, je n'ai pas trouvé beaucoup de sens entrestd::async et le thread pooling moi-même, sauf que std::async crée et supprime automatiquement un thread pour la tâche en cours.
Et pour utiliser le pooling de threads, vous devez connaître à l'avance le nombre de threads utilisés dans le programme, et définir explicitement ce nombre pour le pool.
Il s'avère que le thread pooling est statique en termes de nombre de threads, bien que cela puisse ne pas être le cas, je ne peux pas l'affirmer.
Mais dans le livre de Williams, il dit que le thread pooling est recommandé lorsqu'il y a de très nombreuses tâches à exécuter dans std::thread.
Et peut-être que cela ne s'applique pas àstd::async, je n'en ai pas encore bien saisi le sens.
Et l'asynchronie est très demandée dans les solutions de mise en réseau, et les stratégies multi-symboles, et pour les calculs chargés est également utile.
Mais avecstd::async et std::promise dans la norme, je pense qu'il n'est pas nécessaire de créer un pool de threads.

Ainsi, l'objectif principal de l'asynchronisme est d'utiliser le pool de threads, de se débarrasser de la surcharge liée à la création et à la suppression des threads, si l'asynchronisme ne fait pas cela, alors il est inutile.

En fait, je pensais trop mal de l'asynchronisme, apparemment. Un simple test montre que c'est une chose tout à fait adéquate :

#include <future>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    cout << "Main thread id: " << this_thread::get_id() << endl;
    for (int i = 0;  i < 2;  ++ i){
       cout << "------------------------" << endl;
       vector<future<void>> futures;
       for (int i = 0; i < 10; ++i)
       {
          this_thread::sleep_for(1 ms);
          auto fut = async([]{
                              this_thread::sleep_for(1 s);
                              cout << this_thread::get_id() << '\n';
                           });
          futures.push_back(move(fut));
       }
       for (auto &f : futures)
          f.wait();
    }

    cout << endl;
}

Main thread id: 140657228855104

140657228850944
140657220458240
140657212065536
140657203672832
140657195280128
140657186887424
140657178494720
140657170102016
140657161709312
140657153316608
------------------------
140657153316608
140657161709312
140657170102016
140657178494720
140657228850944
140657220458240
140657212065536
140657203672832
140657195280128
140657186887424

Vous pouvez voir que pour le deuxième lot de travaux, async a utilisé les threads précédemment créés et n'en a pas créé de nouveaux. Donc je ne l'ai pas vraiment dilué de façon méritée, je suppose.

 
Roman:

Il y a aussi une question sur la mise en place d'un projet pour dll.
Comment puis-je me débarrasser des fonctions inutilisées qui sont automatiquement tirées dans la dépendance de la dll par les compilateurs ?

Pour mingw l'option -static devrait aider avec static il arrête de générer des pic.

 

Test asynchrone plus difficile

#include <future>
#include <iostream>
#include <vector>
#include <mutex>
#include <set>
using namespace std;

mutex mtx;
set<thread::id> id;
atomic<unsigned> atm{0};

int main()
{
   for (int i = 0;  i < 10000;  ++ i) {
      vector<future<void>> futures;
      for (int i = 0; i < 10; ++i) {
         auto fut = async(launch::async,[]{
                                           ++ atm;
                                           lock_guard<mutex> lck{mtx};
                                           id.insert( this_thread::get_id() );
                                        });
         futures.push_back(move(fut));
      }
   }

   cout << "executed " << atm << " tasks, by " << id.size() << " threads\n";
}
// cout: executed 100000 tasks, by 10 threads

Eh bien, oui, ça marche bien. Pourquoi ai-je pensé si mal de lui ? Probablement une implémentation tordue à l'aube de c++11 ...

SZY : mais je dois noter que async() anormalement lent avec la politique lanch::async, si vous le remplacez par lanch::deferred (+ attendre la fin du travail à la fin du premier cycle), alors ce simple test commence à fonctionner 30 fois plus vite ! !! Tant pis pour le multithreading ;))). Cela laisse donc de la place pour un pool de fils fait maison, il me semble qu'il peut être fait beaucoup plus rapidement que le standard.

 
Roman:

Il y a aussi une question sur la mise en place d'un projet pour dll.
Comment se débarrasser des fonctions inutilisées, qui sont automatiquement tirées dans la dépendance de la dll par les compilateurs ?

J'ai déjà essayé différents IDE, et chacun d'eux tire sa propre fonction inutilisée.
MSVS_2017 tire même ses propres dépendances temporelles, dont je suppose que je ne peux pas me débarrasser.

Le prendre pour acquis et l'oublier, ou l'oublier.
Qu'est-ce que c'est et pourquoi est-ce une nuisance ? Laissez les bêtises aux voisins).
Les langages de haut niveau sont créés pour que le programmeur ne se soucie pas des détails. Ce n'est pas l'affaire du tsar. Oui, et comment savoir ce dont vous avez besoin et ce dont vous n'avez pas besoin. Le compilateur est le mieux placé pour le savoir.
 
Vict:

Test asynchrone plus difficile

Eh bien, oui, ça marche bien. Pourquoi ai-je pensé si mal de lui ? Probablement une implémentation tordue à l'aube de c++11 ...

SZY : mais je dois noter que async() anormalement lent avec la politique lanch::async, si vous le remplacez par lanch::deferred (+ attendre la fin du travail à la fin du premier cycle), alors ce simple test commence à fonctionner 30 fois plus vite ! !! Tant pis pour le multithreading ;)). Cela laisse donc de la place pour un pool de fils fait maison, il me semble qu'il peut être fait beaucoup plus rapidement que le standard.

Je n'ai pas lu jusqu'au bout et j'ai décidé de vous suggérer de courir avec le drapeau différé ))))). C'est logique, si un tel test fonctionne plus rapidement, je pense généralement que cette façon de l'utiliser est préférable, pourquoi mettre des limites rigides. Je voulais juste dire merci pour votre lien vers Git, je l'ai regardé avec intérêt ;)) J'ai apprécié qu'il existe deux versions - avec et sans boost.

Romain:

Une autre question a été soulevée concernant la mise en place du projet pour le dll.
Comment puis-je me débarrasser des fonctions inutilisées, qui sont automatiquement tirées dans la dépendance de la dll par les compilateurs ?

J'ai déjà essayé différents environnements de développement, et chacun d'eux tire sa propre fonction inutilisée.
MSVS_2017 tire même ses propres dépendances temporelles, dont je suppose que je ne peux pas me débarrasser.
C'est pourquoi j'ai essayé différents IDE, mais ils retirent également des fonctions inutilisées.
Comment s'en débarrasser ?

Comment faire sans divaguer ? Et oui, c'est différent partout. Non, sans rantime il n'y a pas de poussée ou de traction )))) Vous n'avez pas encore travaillé avec QT, c'est là que l'on tire toute une guirlande de saucisses DLL.


 
Andrei Novichkov:

Je n'ai pas lu jusqu'au bout et j'ai décidé de vous suggérer de fonctionner avec le drapeau différé )))).



Pourquoi avons-nous besoin de async() avec le drapeau différé ? Je ne comprends vraiment pas, pouvez-vous m'expliquer ?

 
Vict:

Pourquoi avons-nous besoin de async() avec le drapeau différé ? Je ne comprends vraiment pas, pouvez-vous m'expliquer ?

En fait, pourquoi ne pas lire le drapeau dans la documentation ? Sur https://en.cppreference.com . Et des exemples avec discussion sur stackoverflow.com. J'ai l'habitude d'utiliser ces sources d'information, et je vous conseille d'en faire autant.

 
Andrei Novichkov:

Pourquoi ne pas lire la documentation sur le drapeau ? Sur https://en.cppreference.com . Et des exemples avec discussion sur stackoverflow.com. J'ai l'habitude d'utiliser ces sources d'information, et je vous conseille d'en faire autant.

MSDN. Documentation complète. Le reste n'est que du matériel supplémentaire.