2016-11-04 8 views
4

저는 멀티 스레드 프로그래밍을 처음 접했고 C++ 11에서 std::atomic을 발견했습니다.어떻게하면 C++ 11 std :: atomic을 제대로 늘릴 수 있습니까?

그래서 원자력 작업에 소요되는 시간을 파악하려고했습니다.

using namespace std; 
using namespace std::chrono; 

constexpr int NUM_THREADS = 8; 
constexpr int LIMIT = 100000; 

atomic<int> sum = 0; 

void foo(int idx) { 
    while (true) { 
     if (sum.load() >= LIMIT) { 
      return; 
     } 
     sum.fetch_add(1); 
    } 
} 

main과 :

int main(void) { 
    thread threads[NUM_THREADS]; 

    auto start = high_resolution_clock::now(); 

    for (int i = 0; i < NUM_THREADS; i++) { 
     threads[i] = thread(&foo, i); 
    } 

    for (int i = 0; i < NUM_THREADS; i++) { 
     threads[i].join(); 
    } 
    auto du = high_resolution_clock::now() - start; 

    cout << "computing time\t\t" << duration_cast<milliseconds>(du).count() << "ms" << endl; 
    cout << "number of thread\t" << NUM_THREADS << endl; 
    cout << "sum\t\t\t" << sum << endl; 

    return 0; 
} 

그러나 sumLIMIT 동일 항상하지

나는이 코드를 시도했다.

제가 아는 바로는 atomic 연산은 '호출'될 때 스레드로부터 안전합니다. 그래, 내 코드가 잘못되었다고 생각하지만이 작업을 올바르게 수행하는 방법을 찾지 못했습니다.

main으로 어떻게 정확한 결과를 얻을 수 있습니까? 이 코멘트에 말한 것처럼 문제는 변수 것을

(물론,이 버전은 sumLIMIT 동일 할 것입니다,하지만 난이 좋은 방법이 아니라고 생각 ...)

void foo(int idx) { 
    for (int i = 0; i < LIMIT/NUM_THREADS; i++) { 
     sum.fetch_add(1); 
    } 
} 
+2

첫 번째 검사는 귀하의 수표와 증분이 두 개의 별도 작업이므로 두 개의 스레드가 잠재적으로 LIMIT보다 낮은 값을 읽을 수 있고 둘 다 증가 할 수 있습니다. – Borgleader

+0

문제는 원자를 증가시키는 방법이 아닙니다. 문제는 원자 적으로 * 두 개의 연산을 수행하는 방법입니다. – Hurkyl

+2

http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange 또는 뮤텍스가 필요합니다. –

답변

5

입니다 로드 할 때와 증가 할 때 사이에 다른 스레드에 의해 변경됩니다.

루프를 변경할 수 있습니다. 예 : 이런 식으로 문제를 해결하기 :

while (true) { 
    auto current = sum.load();   
    if (current >= LIMIT) { 
     return; 
    } 
    auto next = current + 1; 
    sum.compare_exchange_strong(current, next)); 
} 
+0

와우. cppreference.com에서 탈출했다. 정말 고마워! –

-1

operator++가 원자 유형에 원자, 그래서 당신이 할 필요가 이것이다 : 스레드 중 하나가 증가하면

void foo(int idx) { 
    while (true) { 
     if (sum++ >= LIMIT) { 
      return; 
     } 
    } 
} 

sumLIMIT에,의 나머지 쓰레드는 값이 LIMIT보다 크거나 같음을 알게 될 것입니다. 여기서 한 가지 위험이 있습니다. 스레드 수가 std::numeric_limits<int>::max() - LIMIT보다 큰 경우 나중 스레드 중 하나가 을 넘어서 int의 최대 값을 초과합니다. 마찬가지로 LIMIT 감각입니다 <g>이 문제가되지 않습니다.