📌 목표

  • 소수 판단 함수 구현
  • 범위를 나누어 쓰레드 별로 병렬 처리
  • thread::hardware_concurrency() 를 통한 최적 코어 수 활용
  • std::threadstd::async/future 방식 모두 실험

🧮 1. 소수 판별 함수 IsPrime()

bool IsPrime(int number)
{
    if (number <= 1)
        return false;
    if (number == 2 || number == 3)
        return true;

    for (int i = 2; i < number; i++)
    {
        if (number % i == 0)
            return false;
    }
    return true;
}
  • 23은 예외적으로 소수로 처리
  • 2부터 number-1까지 나눠 떨어지는 수가 있으면 소수가 아님

📌 Tip: 실제 성능 향상을 위해선 i <= sqrt(number)까지만 순회해도 되지만, 여기선 단순 구현!


🧮 2. 소수 개수 구하기 CountPrime()

int CountPrime(int start, int end)
{
    int count = 0;
    for (int number = start; number <= end; number++)
    {
        if (IsPrime(number))
            count++;
    }
    return count;
}
  • 특정 범위에서 소수 개수 누적
  • 멀티 쓰레드로 각 범위를 나누어 이 함수를 사용함

⚙️ 3. 멀티 쓰레드 방식 - std::thread

int main()
{
    const int MAX_NUMBER = 1'000'000;

    vector<thread> threads;

    int coreCount = thread::hardware_concurrency();
    int jobCount = (MAX_NUMBER / coreCount) + 1;

    atomic<int> primeCount = 0;

    for (int i = 0; i < coreCount; i++)
    {
        int start = (i * jobCount) + 1;
        int end = min(MAX_NUMBER, ((i + 1) * jobCount));

        threads.push_back(thread([start, end, &primeCount]()
        {
            primeCount += CountPrime(start, end);
        }));
    }

    for (thread& t : threads)
        t.join();

    cout << primeCount << endl;
}

✅ 핵심 포인트

  • 코어 수만큼 쓰레드 생성 (hardware_concurrency())
  • 각 쓰레드에 작업 범위를 분산
  • atomic<int>으로 공유 자원(primeCount)의 데이터 레이스 방지
  • thread.join()으로 모든 쓰레드 종료 대기

⚙️ 4. Future 방식 - std::async + shared_future

int main()
{
    const int MAX_NUMBER = 1'000'000;
    const int MAX_THREAD = thread::hardware_concurrency();

    int stepVal = MAX_NUMBER / MAX_THREAD;
    int sum = 0;

    vector<shared_future<int>> futures;

    for (int i = 1; i <= MAX_THREAD; ++i)
    {
        shared_future<int> f = async(launch::async, CountPrime, stepVal * (i - 1), stepVal * i);
        futures.push_back(f);
    }

    if (stepVal * MAX_THREAD < MAX_NUMBER)
    {
        sum += CountPrime(stepVal * MAX_THREAD + 1, MAX_NUMBER);
    }

    for (auto& f : futures)
        sum += f.get();

    cout << sum << endl;
}

✅ 특징 요약

  • async를 이용해 비동기 호출로 작업 수행
  • shared_future를 통해 복수 참조 가능
  • get() 호출로 각 작업 결과 수집

⚡ 성능 비교

방식1,000,000 소수 계산 시간특징
std::thread더 빠름직접 제어, 가벼움
std::async조금 느림코드 간결함, 내부 제어 비용 있음

profile
李家네_공부방

0개의 댓글