我一直在嘗試使用std::async。我寫了一個(非常低效的)函式,它將所有質數相加到一個給定的極限。
在沒有std::async的情況下,該函式總是給出由ctest單元測驗判斷的預期結果。使用std::async但沒有std::lock_guard/mutex,預期值和計算值之間有很大的偏差(正如預期)。使用 std::lock_guard / mutex,結果仍然是不可復制的,在大約 50% 的測驗中給出了正確的結果,在另外 50% 的測驗中,數值偏離了 1-2(例如,9151 而不是 9152)。
我正在討論是否因為我的isPrime(int)函式引入了另一個瓶頸而出現了問題。或者,我認為程式(有時)會在最后一個執行緒完成作業之前過早地終止。
無論哪種情況,我都不明白為什么std::lock_guard似乎不能保護變數count。
// primeAsync.cc。
#include <future>
#include <vector>
#include "primAsync.h"
#include "prime.h"
//mutex for thread safety
static std::mutex s_PrimeMutex。
///handle to store futures
static std::vector<std::future<void>> s_Futures;
static void countPrimesHelper(int* count, const long long number>;
///每隔一段時間就會通過ctest,計數偏離1-2(例如9151而不是9152)。
int countPrimesAsync(const long long limit) {
int count = 0;
for(long i = 2; i < limit; i) {
s_Futures.push_back(std::async(std:: launch::async, countPrimesHelper, &count, i))。
}
return count。
}
// countPrimesAsync的輔助函式,std::async。
static void countPrimesHelper(int* count, const long long number) {
if(isPrime(number)) {
const std::lock_guard<std::mutex> lock(s_PrimeMutex)。
(*count)。
}
// prime.cc
#include <iostream>
#include <vector>
//總是通過ctest。
bool isPrime(const long long n) {
int mod;
for(long long m = n - 1; m > 1; -- m) {
mod = n % m;
if(mod == 0) {
return false;
}
}
return true;
}
//總是通過ctest。
int countPrimes(const long long limit) {
int count = 0;
for(long i = 2; i < limit; i) {
if(isPrime(i)) {
count ;
}
}
return count。
}
uj5u.com熱心網友回復:
另一件人們沒有提到的事情是,原子變數允許你有一個被多個執行緒訪問和寫入的值,而沒有競賽條件,并且會比鎖保護快很多。
例如:
#include <atomic>/span>
std::atomic<int> count;
static void countPrimesHelper(std:: atomic<int>* count, const long long number) {
if(isPrime(number)) {
(*count) = 1;
}
}
這是無競賽條件的,即使有100萬個執行緒在訪問計數。它的作業原理是將增量作為一個操作,在不完整的狀態下不能被訪問。它還可以防止你的處理器(如果你有一個最新的處理器)并行地進行這個操作。(使用一個持續一個操作的低級鎖指令)
這里有更多的資訊。
這里有更多關于原子頭的資訊。https://en.cppreference.com/w/cpp/atomic
uj5u.com熱心網友回復:
我改變了函式,以等待所有的期貨完成后再回傳計數:
我改變了函式,以等待所有的期貨完成后再回傳計數。
//現在似乎每次都能通過ctest。
int countPrimesAsync(const long long limit) {
int count = 0;
for(long i = 2; i < limit; i) {
s_Futures.push_back(std::async(std:: launch::async, countPrimesHelper, &count, i))。
}
for(long i = 0; i < s_Futures.size(); i) {
s_Futures[i].wait()。
}
return count;
}
該方案通過了測驗!
另外,我找到了以下解決方案來檢查未來的狀態:
獲取一個 std::future 的狀態不確定哪一個是首選(如果有的話)。
不過已經謝謝你了!
與 Fran?ois Andrieux 一致,這個解決方案也可以作業并通過 ctest,不需要一個靜態變數,而且我認為比第二個 for 回圈更優雅:
//現在似乎每次都能通過 ctest。
int countPrimesAsync(const long long limit) {
//span>柄來存盤期貨。
std::vector<std::future<void>> s_Futures。
int count = 0;
for(long i = 2; i < limit; i) {
s_Futures.push_back(std::async(std:: launch::async, countPrimesHelper, &count, i))。
}
s_Futures.clear()。
return count;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/308332.html
標籤:
上一篇:<p>這是我做的一個簡化的例子,以暴露我的問題。我有一些任務<code>doSomeWork()</code>,我使用ExecutorService以多執行緒方式處
