Programmazione asincrona e multithread in MQL - pagina 34

 
Andrei Novichkov:
Ma mi chiedo se ci sono compiti che richiedono davvero il thread pooling? Non solo - creare un filo, dimenticarlo e aspettare che si esaurisca, ma esattamente un pool, come lo descrive Williams? Sembra essere un esempio di bancomat lì, se non mi sbaglio - quale compito potrebbe giustificare un tale miracolo di judo? Non riesco ancora a pensare a un tale compito. E perché non guardi ThreadPool dove tutto è già fatto, c'è documentazione ed esempi.

Ad essere onesti, finora non ho visto molto senso trastd::async e thread pool, tranne chestd::async crea e cancella automaticamente un thread per il compito a portata di mano.
E per utilizzare il thread pooling, è necessario conoscere in anticipo il numero di thread utilizzati nel programma, e impostare questo numero per il pool in modo esplicito.
Risulta che il thread pooling è statico in termini di numero di thread, anche se questo potrebbe non essere il caso, non posso affermarlo.
Ma nel libro di Williams, dice che il thread pooling è raccomandato quando ci sono molti compiti da eseguire in std::thread.
E forse questo non si applica astd::async, non ho ancora afferrato completamente il significato.
E l'asincronia è molto richiesta nelle soluzioni di rete, e le strategie multisimbolo, e per i calcoli caricati è anche utile.
Ma avendostd::async e std::promise nello standard, penso che non ci sia bisogno di creare un pool di thread.

 

C'è anche una domanda sull'impostazione di un progetto per dll.
Come sbarazzarsi delle funzioni inutilizzate, che sono automaticamente tirate nella dipendenza della dll dai compilatori?

Ho già provato diversi ambienti di sviluppo, e ognuno di essi tira la sua funzione inutilizzata.
MSVS_2017 tira anche le sue dipendenze runtime, di cui credo di non potermi liberare.
Perciò ho provato diversi IDE, ma anche loro tirano fuori funzioni inutilizzate.
Come sbarazzarsi di loro?

 
Roman:

Ad essere onesti, io stesso non ho colto molto senso trastd::async e il thread pooling, tranne che std::async crea e cancella automaticamente un thread per il compito a portata di mano.
E per utilizzare il thread pooling, è necessario conoscere in anticipo il numero di thread utilizzati nel programma, e impostare questo numero per il pool in modo esplicito.
Risulta che il thread pooling è statico in termini di numero di thread, anche se questo potrebbe non essere il caso, non posso affermarlo.
Ma nel libro di Williams, dice che il thread pooling è raccomandato quando ci sono molti compiti da eseguire in std::thread.
E forse questo non si applica astd::async, non ho ancora afferrato completamente il significato.
E l'asincronia è molto richiesta nelle soluzioni di rete, e le strategie multisimbolo, e per i calcoli caricati è anche utile.
Ma avendostd::async e std::promise nello standard, penso che non ci sia bisogno di creare un pool di thread.

Quindi il punto principale di async è quello di utilizzare il pool di thread, sbarazzarsi dell'overhead di creazione/cancellazione dei thread, se async non lo fa, allora è inutile.

Beh, in realtà, stavo pensando troppo male all'async, a quanto pare. Un semplice test lo mostra come una cosa abbastanza adeguata:

#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

Potete vedere che per il secondo gruppo di lavori async ha usato i thread precedentemente creati e non ne ha creati di nuovi. Quindi non è che lo stessi annacquando meritatamente, credo.

 
Roman:

C'è anche una domanda sull'impostazione di un progetto per dll.
Come posso sbarazzarmi delle funzioni inutilizzate che sono automaticamente tirate nella dipendenza della dll dai compilatori?

Per mingw l'opzione -static dovrebbe aiutare con static che smette di generare pic

 

Test asincrono più severo

#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

Beh, sì, funziona bene. Perché ho pensato così male? Probabilmente un'implementazione storta agli albori di c++11 ...

SZY: ma dovrei notare che async() anormalmente lento con la politica di lanch::async, se lo si sostituisce con lanch::deferred (+ attendere il completamento del lavoro alla fine del primo ciclo), allora questo semplice test inizia a funzionare 30 volte più velocemente!!! Alla faccia del multithreading ))). Quindi questo lascia spazio per un pool di fili fatto in casa, mi sembra che possa essere fatto molto più velocemente di quello standard.

 
Roman:

C'è anche una domanda sull'impostazione di un progetto per dll.
Come sbarazzarsi delle funzioni inutilizzate, che sono automaticamente tirate nella dipendenza della dll dai compilatori?

Ho già provato diversi IDE, e ognuno di loro tira la sua funzione inutilizzata.
MSVS_2017 tira anche le sue dipendenze temporali, di cui credo di non potermi liberare.

Darlo per scontato e dimenticarlo, o dimenticarlo.
Cosa e perché è un fastidio? Lasciate le sciocchezze ai vicini).
I linguaggi di alto livello sono creati in modo che un programmatore non si preoccupi dei dettagli. Non sono affari dello zar. Sì, e come si fa a sapere di cosa si ha bisogno e di cosa non si ha bisogno. Il compilatore lo sa meglio di tutti.
 
Vict:

Test asincrono più severo

Beh, sì, funziona bene. Perché ho pensato così male? Probabilmente un'implementazione storta agli albori di c++11 ...

SZY: ma dovrei notare che async() anormalmente lento con la politica di lanch::async, se lo si sostituisce con lanch::deferred (+ attendere il completamento del lavoro alla fine del primo ciclo), allora questo semplice test inizia a funzionare 30 volte più velocemente!!! Alla faccia del multithreading )). Quindi questo lascia spazio per un pool di fili fatto in casa, mi sembra che possa essere fatto molto più velocemente di quello standard.

Non ho letto fino alla fine e ho deciso di suggerirvi di correre con la bandiera differita ))))) Ha senso, se un tale test gira più velocemente, in generale penso che questo modo di usarlo sia preferibile, perché mettere dei limiti rigidi. Volevo solo dire grazie per il tuo link a Git, l'ho guardato con interesse )) Mi è piaciuto che ci sono due versioni - con e senza spinta.

Romano:

È venuta fuori un'altra domanda sull'impostazione del progetto per il dll.
Come posso sbarazzarmi delle funzioni inutilizzate, che sono automaticamente tirate nella dipendenza della dll dai compilatori?

Ho già provato diversi ambienti di sviluppo, e ognuno di essi tira la sua funzione inutilizzata.
MSVS_2017 tira anche le sue dipendenze temporali, di cui credo di non potermi liberare.
Perciò ho provato diversi IDE, ma anche loro tirano fuori funzioni inutilizzate.
Come sbarazzarsi di loro?

Come si può fare a meno di farneticare? E sì, è diverso ovunque. No, senza rantime non si può spingere o tirare )))) Non hai ancora lavorato con QT, è lì che si tira tutta una ghirlanda di salsicce DLL.


 
Andrei Novichkov:

Non ho letto fino alla fine e ho deciso di suggerirvi di correre con la bandiera differita ))))



Perché abbiamo bisogno di async() con il flag differito? Davvero non capisco, puoi spiegarmi?

 
Vict:

Perché abbiamo bisogno di async() con il flag differito? Davvero non capisco, puoi spiegarmi?

Infatti, perché non leggete la bandiera nella documentazione? Su https://en.cppreference.com . Ed esempi con discussione su stackoverflow.com. Di solito uso queste fonti di informazione, e vi consiglio di fare lo stesso.

 
Andrei Novichkov:

Perché non leggere effettivamente la bandiera nella documentazione? Su https://en.cppreference.com . Ed esempi con discussione su stackoverflow.com. Di solito uso queste fonti di informazione, e vi consiglio di fare lo stesso.

MSDN. Documentazione completa. Il resto è solo materiale supplementare.
Motivazione: