2016-06-10 14 views
2

Ich habe Code, der Aufgaben an ein asio io_service Objekt zur Remote-Verarbeitung löst. Soweit ich das beurteilen kann, verhält sich der Code korrekt, aber leider weiß ich nicht viel über die Speicherordnung, und ich bin mir nicht sicher, welche Speicherordnungen ich verwenden sollte, wenn ich die atomaren Flags überprüfe, um eine optimale Leistung sicherzustellen.Welche Speicherreihenfolge sollte ich für einen Host Thread verwenden, der auf Worker Threads wartet?

//boost::asio::io_service; 
//^^ Declared outside this scope 
std::vector<std::atomic_bool> flags(num_of_threads, false); 
//std::vector<std::thread> threads(num_of_threads); 
//^^ Declared outside this scope, all of them simply call the run() method on io_service 

for(int i = 0; i < num_of_threads; i++) { 
    io_service.post([&, i]{ 
     /*...*/ 
     flags[i].store(true, /*[[[1]]]*/); 
    }); 
} 

for(std::atomic_bool & atm_bool : flags) while(!atm_bool.load(/*[[[2]]]*/)) std::this_thread::yield(); 

Also im Grunde, was ich wissen will, ist, was soll ich in für [[[1]]] und [[[2]]] ersetzen?

Wenn es hilft, ist der Code funktional ähnlich dem folgenden:

std::vector<std::thread> threads; 
for(int i = 0; i < num_of_threads; i++) threads.emplace_back([]{/*...*/}); 
for(std::thread & thread : threads) thread.join(); 

Außer, dass mein Code die Fäden am Leben in einem Außengewinde Pool hält und löst Aufgaben, die ihnen.

+0

Lassen Sie im Zweifelsfall die vollen Speicherbarrieren bestehen (Standard). – SergeyA

Antwort

2

Sie möchten eine happes-before-Beziehung zwischen dem Thread, der das Flag und den Thread setzt, feststellen, dass es gesetzt wurde. Das heißt, sobald der Thread das Flag gesetzt hat, sieht er auch die Auswirkungen von allem, was der andere Thread getan hat, bevor er es setzt (dies ist nicht garantiert).

Dies kann mit Release-erwerben Semantik erfolgen:

flags[i].store(true, std::memory_order_release); 
// ... 
while (!atm_bool.load(std::memory_order_acquire)) ... 

Beachten Sie, dass es in diesem Fall könnte sauberer sein, um eine Blockierung OS-Ebene Semaphore zu verwenden, als auf eine Reihe von Flaggen Spin-warten. Wenn das nicht gelingt, wäre es immer noch ein wenig effizienter, die Anzahl der abgeschlossenen Aufgaben zu berechnen, anstatt für jede eine Reihe von Flags zu prüfen.

+0

FYI, laden-akquirieren und speichern-release sind kostenlos auf x86 (laden und speichern alle haben erwerben/release semantik builtin), aber Sie müssen immer noch schreiben sie aus, weil der Compiler ist anders zu ordnen Dinge (und es ist tragbar und richtig so auch). – Cameron

Verwandte Themen