본문 바로가기
-----ETC-----/C++ 성능 최적화 및 고급 테크닉 시리즈

[C++ 성능 최적화 및 고급 테크닉] Day 17: 병렬 알고리즘과 std::async

by cogito21_cpp 2024. 8. 1.
반응형

병렬 알고리즘의 중요성

병렬 알고리즘은 여러 작업을 동시에 수행하여 프로그램의 성능을 극대화하는 데 도움을 줍니다. C++17에서는 표준 라이브러리에 병렬 알고리즘을 도입하여, 쉽게 병렬 처리를 구현할 수 있습니다.

 

병렬 알고리즘

C++17 표준 라이브러리에서는 병렬 알고리즘을 지원하기 위해 std::execution 네임스페이스를 도입했습니다. 이를 통해 기존 알고리즘을 병렬로 실행할 수 있습니다.

 

std::execution 정책

  • seq: 순차적으로 실행
  • par: 병렬로 실행
  • par_unseq: 병렬로 실행하고, 실행 순서는 정의되지 않음

 

예제 코드

병렬 정렬

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

int main() {
    std::vector<int> vec = {5, 2, 9, 1, 5, 6};

    // 병렬로 정렬
    std::sort(std::execution::par, vec.begin(), vec.end());

    for (int n : vec) {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    return 0;
}

 

std::async

std::async는 비동기 작업을 생성하고 관리하는 데 사용되는 함수 템플릿입니다. 이를 통해 함수 호출을 비동기적으로 수행할 수 있습니다.

 

std::async의 사용법

std::async는 호출할 함수와 함수의 인자를 받아 비동기 작업을 생성합니다. 반환된 std::future 객체를 통해 결과를 얻을 수 있습니다.

 

예제 코드

#include <iostream>
#include <future>

int compute() {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 작업 지연
    return 42;
}

int main() {
    // 비동기 작업 생성
    std::future<int> result = std::async(std::launch::async, compute);

    // 결과를 기다리고 얻음
    std::cout << "Result: " << result.get() << std::endl;

    return 0;
}

 

std::future와 std::promise

  • std::future: 비동기 작업의 결과를 나타냅니다. get() 함수를 호출하여 결과를 얻을 수 있습니다.
  • std::promise: 비동기 작업의 결과를 설정하는 데 사용됩니다. set_value() 함수를 호출하여 결과를 설정할 수 있습니다.

예제 코드

#include <iostream>
#include <thread>
#include <future>

void compute(std::promise<int> prom) {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 작업 지연
    prom.set_value(42);
}

int main() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();

    // 별도의 스레드에서 작업 수행
    std::thread t(compute, std::move(prom));

    // 결과를 기다리고 얻음
    std::cout << "Result: " << fut.get() << std::endl;

    t.join();
    return 0;
}

 

실습 문제

문제 1: std::async와 병렬 알고리즘 사용하기

다음 코드에서 std::async와 병렬 알고리즘을 사용하여 벡터의 요소를 비동기적으로 정렬하고, 병렬로 합계를 계산하세요.

 

main.cpp

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>

int main() {
    std::vector<int> vec = {5, 2, 9, 1, 5, 6};

    // 비동기적으로 벡터 정렬
    auto sortFuture = std::async(std::launch::async, [&vec]() {
        std::sort(vec.begin(), vec.end());
    });

    sortFuture.get(); // 정렬 완료 대기

    // 병렬로 벡터 합계 계산
    int sum = std::reduce(std::execution::par, vec.begin(), vec.end());

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}

 

해답:

main.cpp (최적화)

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>
#include <execution>

int main() {
    std::vector<int> vec = {5, 2, 9, 1, 5, 6};

    // 비동기적으로 벡터 정렬
    auto sortFuture = std::async(std::launch::async, [&vec]() {
        std::sort(std::execution::par, vec.begin(), vec.end());
    });

    sortFuture.get(); // 정렬 완료 대기

    // 병렬로 벡터 합계 계산
    int sum = std::reduce(std::execution::par, vec.begin(), vec.end());

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}

 

이제 열일곱 번째 날의 학습을 마쳤습니다. 병렬 알고리즘과 std::async의 사용법을 이해하고, 이를 사용하여 성능을 최적화하는 방법을 학습했습니다.

질문이나 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "고급 멀티스레딩 기법 (락 프리 프로그래밍)"에 대해 학습하겠습니다.

반응형