이번 시간에는 병렬 STL, atomic 스마트포인터에 대해 알아보겠습니다

parallel STL

다중 코어 환경에서 병렬 STL

#include <iostream>
#include <algorithm>
#include <vector>
#include <thread>
#include <execution>

void foo(int n )
{
    std::cout << n << " : " << std::this_thread::get_id() << std::endl;
}

int main()
{
    std::vector<int> v{1,2,3,4,5,6,7,8,9,10};

    std::for_each(std::execution::par, v.begin(), v.end(), foo);
}
  • execution 종류
    • std::execution::seq : 싱글 스레드
    • std::execution::par : 알고리즘 병렬 실행
    • std::execution::par_unseq : 알고리즘 병렬 실행(SIMD 방식)
    • std::execution::unseq : 싱글 스레드(SIMD 방식, C++ 20)

병렬 알고리즘 사용시 주의점

  • 다중 스레드 환경이기 때문에 외부 변수를 대상으로 병렬 STL이 동작 할 경우 동기화가 필요함
#include <iostream>
#include <algorithm>
#include <vector>
#include <thread>
#include <execution>
#include <mutex>
#include <chrono>
using namespace std::literals;

int main()
{
    std::vector<int> v(100, 0);

    for ( int i = 1 ; i <= 100; i++)
        v.push_back(i);  
    
//    std::mutex m;
//    int sum = 0;

    std::atomic<int> sum = 0;
    
    std::for_each(std::execution::par, v.begin(), v.end(), [&](int n) { 
            //std::lock_guard<std::mutex> lg(m);
            //sum += n;
            sum.fetch_add(n, std::memory_order_relaxed);
            std::this_thread::sleep_for(1ms);
        } );

    std::cout << sum << '\n';
}

atomic smart pointer

  • 참조 캡쳐로 shared_ptr 사용시 다중 스레드 환경에서 안전하지 않음
  • atomic smart pointer 사용시 안전
#include <iostream>
#include <thread>
#include <atomic>
#include <memory>

void goo()
{
//    std::shared_ptr<int> ptr = std::make_shared<int>(5);

    // C++20 부터 아래 코드 허용.
    std::atomic<std::shared_ptr<int>> ptr = std::make_shared<int>(5);

    // 참조에 의한 캡쳐
    std::thread t1( [&ptr]() //mutable 
    { 
        ptr = std::make_shared<int>(1);
    });

    std::thread t2( [&ptr]() //mutable 
    { 
        ptr = std::make_shared<int>(2);
    }); 
    
    t1.join();
    t2.join();
}

int main()
{
    goo();
}