MQL'de asenkron ve çok iş parçacıklı programlama - sayfa 36

 
Vict :

Aklıma gelen tek mantıklı açıklama havuzda çalışan thread sayısı üzerinde manuel kontrol (varsayılan async | deferred'e güvenmiyorsak) - örneğin, sistemin çok yüklendiğini görüyoruz, görev göndermeyi bırakıyoruz. zaman uyumsuz bayrak ile ertelenmiş göndeririz.

Genel olarak, async'in () yavaşlığından biraz hayal kırıklığına uğradım, hafif iplik havuzumu uydurmak için zamanım olacak, bana öyle geliyor ki çok daha hızlı olacak.

Varsayılan zaman uyumsuz|ertelenmiş modu, kitapta şu anda yeterli fiziksel kaynak yoksa, görev yeni bir iş parçacığı oluşturmayacak, ancak ana iş parçacığında engellenerek yürütülecek şekilde açıklanmıştır.
Ve varsayılan modda ana iş parçacığının olası engellenmesini her zaman hatırlamalısınız, çünkü temel olarak, aksine, ana iş parçacığını engellememek için çözümlere ihtiyaç vardır.
Yani varsayılan mod, fiziksel kaynak, yani işlemci üzerindeki yüke bağlı olarak görevin nerede yürütüleceğini otomatik olarak değiştirir.
Bu nedenle, fiziksel kaynağın taşmayacağından eminsek, bayrağı açıkça std::launch::async belirtmek daha iyidir.
Ve modern işlemcilerin fiziksel kaynağını aşmak için, tam potansiyeli seçmek için bu tür hesaplamaları aramak hala gereklidir))
Hala teori çalıştığım için hız hakkında henüz bir şey söyleyemem))

 
Roman :

Bu nedenle, fiziksel kaynağın taşmayacağından eminsek, bayrağı açıkça std::launch::async belirtmek daha iyidir.
Ve modern işlemcilerin fiziksel kaynağını aşmak için, tam potansiyeli seçmek için bu tür hesaplamaları aramak hala gereklidir))

İşlemci en azından bir dizi iş parçacığına dayanacak, ancak işletim sisteminin yetenekleri - daha ziyade bir darboğaz olacak. Eh, sonsuz sayıda iş parçacığı üretemez, er ya da geç async(lauch::async, ...) atılmış bir istisna ile karşılaşacaktır.

 
Vict :

İşlemci en azından bir dizi iş parçacığına dayanacak, ancak işletim sisteminin yetenekleri - daha ziyade bir darboğaz olacak. Eh, sonsuz sayıda iş parçacığı üretemez, er ya da geç async(lauch::async, ...) atılmış bir istisna ile karşılaşacaktır.

Evet, fiziksel sınır her zaman mevcuttur, ancak MT5 için görevlerimizde bu sınırın ötesine geçmek pek olası değildir.
Ayrıca, dönüş değerlerinde async ve future, bu değeri nasıl elde ettiğimize bakılmaksızın, lambda işlevi, ref() veya .get() aracılığıyla ortaya çıkarlarsa istisnalar döndürür.
Ve dönüş değerindeki std::thread istisnaları döndüremez.

 
Roman :

Evet, fiziksel sınır her zaman mevcuttur, ancak MT5 için görevlerimizde bu sınırın ötesine geçmek pek olası değildir.
Ayrıca, dönüş değerlerinde async ve future, bu değeri nasıl elde ettiğimize bakılmaksızın, lambda işlevi, ref() veya .get() aracılığıyla ortaya çıkarlarsa istisnalar döndürür.
Ve dönüş değerindeki std::thread istisnaları döndüremez.

IMHO, zaman uyumsuzluğa fazla kapılma. Kolaylık sağlamak için yapmışlar gibi görünüyor, ancak tüm bu güzellikler özellikle performansı vuruyor gibi görünüyor. Bu bir artı değil...

Ve dönüş değerindeki std::thread istisnaları döndüremez.

Bu her zaman gerekli değildir. Ancak gerekirse, bu bir düzine ekstra satırdır (daha hızlı çalışmasına rağmen - yığında herhangi bir tahsis olmadan).
 
Vict :
Ancak gerekirse, bu bir düzine ekstra satırdır (daha hızlı çalışmasına rağmen - yığında herhangi bir tahsis olmadan).

Asılsız olmamak için:

#include <thread>
#include <future>
#include <iostream>
#include <chrono>
using namespace std;

template <typename T>
void thread_fn(T &&task) {task( 0 );}

int main()
{
   packaged_task< int ( int )> task{ []( int i){this_thread::sleep_for( 3 s); return i== 0 ? throw 0 : i;} };
   auto f = task.get_future();
   thread t{thread_fn<decltype(task)>, move(task)};
   t.detach();

   try {
      cout << f. get () << endl;
   } catch (...) {
      cout << "exception caught" << endl;
   }

   return 0 ;
}

On bile almadı. Evet, herhangi bir packaged_task ve gelecek olmadan daha da düşük seviyeli olabilir, ancak fikir - istisnalar atmak - bir tür zaman uyumsuz süper özellik değildir ve iş parçacığı hiç değildir.

 
Belki pratik bir bakış açısıyla, bazen tüm bu güzelliklerden uzaklaşmaya ve Windows api - CreateThread'i, senkronizasyon ilkellerini, birbirine bağlı işlevleri hatırlamaya değer olabilir. Yine de var. Tabii ki, Windows için yazıldığında. MT4|MT5'in ertelenmiş hesaplamalar, havuzlar vb. gerektiren karmaşık görevleri yoksa neden karmaşık olsun?
 
Andrei Novichkov :
MT4|MT5'in ertelenmiş hesaplamalar, havuzlar vb. gerektiren karmaşık görevleri yoksa neden karmaşık olsun?
Aslında görevler var. MT'nin seçeneği yoktur.
Burada, her türlü havuz gerçekten gereksiz. Standart multithreading çözümleri doğru kullanıldığında gözler için yeterlidir.
 
Yuriy Asaulenko :
Aslında görevler var. MT'nin seçeneği yoktur.
Burada, her türlü havuz gerçekten gereksiz. Standart multithreading çözümleri doğru kullanıldığında gözler için yeterlidir.
Ben ondan bahsediyorum.
 

Arkadaşlar araştırmamı paylaşıyorum.

İplik havuzumu dizlerimin üzerine yazdım. Bunun tamamen işlevsel bir sürüm olduğuna dikkat edilmelidir, herhangi bir işlevi herhangi bir parametre ile geçebilirsiniz, yanıt olarak bir gelecek döndürülür, yani. istisnaları yakalamak ve tamamlanmasını beklemek şeklinde tüm güzellikler mevcuttur. Ve oradaki gibi kullandım https://www.mql5.com/ru/forum/318593/page34#comment_12700601

 #include <future>
#include <iostream>
#include <vector>
#include <mutex>
#include <set>

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

int main()
{
   Thread_pool p{ 10 };
   for ( int i = 0 ;  i < 10000 ;  ++ i) {
      vector<future< void >> futures;
       for ( int i = 0 ; i < 10 ; ++i) {
         auto fut = p.push([]{
                              ++ 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" ;
}

Kimin std::async yazdığını ve hangi durumda olduğunu bilmiyorum, ancak diz boyu zanaatım standart olandan yaklaşık 4 kat daha hızlı (10 çalışan iş parçacığı ile). Ayrıca, çekirdek sayısından daha fazla iş parçacığı artışı sadece bir yavaşlama sağlar. Havuz boyutu == çekirdek sayısı (2) ile zaman uyumsuz yaklaşık 30 kez kaybeder. Bu kadar.

Bir iş parçacığı havuzu istiyorsam, kesinlikle standart zaman uyumsuz olmayacaktır))).

 
Vict :

Arkadaşlar araştırmamı paylaşıyorum.

İplik havuzumu dizlerimin üzerine yazdım. Bunun tamamen işlevsel bir sürüm olduğuna dikkat edilmelidir, herhangi bir işlevi herhangi bir parametre ile geçebilirsiniz, yanıt olarak bir gelecek döndürülür, yani. istisnaları yakalamak ve tamamlanmasını beklemek şeklinde tüm güzellikler mevcuttur. Ve oradaki gibi kullandım https://www.mql5.com/ru/forum/318593/page34#comment_12700601

Kimin std::async yazdığını ve hangi durumda olduğunu bilmiyorum, ancak diz boyu zanaatım standart olandan yaklaşık 4 kat daha hızlı (10 çalışan iş parçacığı ile). Ayrıca, çekirdek sayısından daha fazla iş parçacığı artışı sadece bir yavaşlama sağlar. Havuz boyutu == çekirdek sayısı (2) ile, async yaklaşık 30 kat kaybeder. Bu kadar.

Bir iş parçacığı havuzu istiyorsam, kesinlikle standart zaman uyumsuz olmayacaktır))).

Araştırma için teşekkürler. İyi bir örnek, çalışmak için düşünülecek bir şey var.
Ancak genel tartışmamızdan çoğumuz, iş parçacığı havuzunun aslında gerçekten gerekli olmadığı sonucuna vardık.
Benim durumumda bu kesin, havuzun iş parçacığı sayısı açısından statik olduğunu fark ettiğim için bu bana uymuyor.
Ve evet, bir havuza ihtiyaç duyulduğunda, o zaman örneğiniz sadece bunun iyiliği için olacaktır. Örnekleri gösterdiğin için teşekkürler.
Hala basit bir anlayışla anlamaya başlıyorum))