728x90

멀티 스레드에서 인접 메모리를 연산하는 경우가 있다고 가정 해보자. cache line이 64byte로 설계되어 있어 64byte보다 작은 데이터를 연산하더라도 인접 메모리까지 포함해서 코어는 64byte를 가져와서 계산하고 이때 현재 계산 대상은 아니지만 다른 코어에서 인접 부분 메모리를 수정하고 있게 된다. 이걸 false sharing 이라고 부르고 이를 해결 하기 위해서 코어간에 sync process를 진행하게 된다.  따라서 오히려 싱글 스레드 연산보다 더 느린 결과 나올 수 있다

 

이런 sync process 과정을 없애기 위한 방법으로 패딩을 넣을 수 있다. 현재 컴퓨터 구조에서는 메모리 자원이 cpu 자원보다 훨씬 저렴하기에 메모리 자원을 낭비하고 CPU 자원을 효율적으로 활용하는 경우가 많다.

 

샘플코드

#include <iostream>
#include <thread>
#include <chrono>
#include <iomanip>

using namespace std;
using namespace chrono;

long long num1 = 0;
long long num2 = 0;
long long num3 = 0;
alignas(64) long long num4 = 0;
alignas(64) long long num5 = 0;

void func1()
{
    for (size_t i = 0; i < 10000000; i++) num1 += 1;
}

void func2()
{
    for (size_t i = 0; i < 10000000; i++) num2 += 1;
}

void func3()
{
    for (size_t i = 0; i < 10000000; i++) num3 += 1;
}

void func4()
{
    for (size_t i = 0; i < 10000000; i++) num4 += 1;
}

void func5()
{
    for (size_t i = 0; i < 10000000; i++) num5 += 1;
}

int main()
{
    const int RANGE = 20000;

    cout.setf(ios::right);
    {
        auto begin = chrono::high_resolution_clock::now();

        func3();
        
        auto end = chrono::high_resolution_clock::now();
        chrono::duration<double> duration = end - begin;

        cout << setw(50) << std::left << "single thread (elapsed time) :: " << setw(10) << duration.count() << endl;
    }

    {
        auto begin = chrono::high_resolution_clock::now();

        thread t1 = thread(func1);
        thread t2 = thread(func2);

        t1.join();
        t2.join();
       
        auto end = chrono::high_resolution_clock::now();
        chrono::duration<double> duration = end - begin;

        cout << setw(50) << "mutli thread (elapsed time) :: " << setw(10) << duration.count() << endl;
    }

    {
        auto begin = chrono::high_resolution_clock::now();

        thread t1 = thread(func4);
        thread t2 = thread(func5);

        t1.join();
        t2.join();

        auto end = chrono::high_resolution_clock::now();
        chrono::duration<double> duration = end - begin;

        cout << setw(50) << "mutli thread + padding (elapsed time) :: " << setw(10) << duration.count() << endl;
    }
}

 

결과

 

728x90

+ Recent posts