[C++11] std::thread

기존의 C++에서의 Thread는 운영체제에 종속되는 API로 제공되거나 비표준이 아닌 라이브러리를 통해 제공되다가 C++11에서 완전한 표준으로써 자리잡아 단일 API로 동일한 코드로 개발이 가능하게 되었습니다. 아래의 코드는 C++11에서 제공하는 std::thread를 사용한 간단한 예입니다.

#include "stdafx.h"
#include 
#include 

using namespace std;

void thread_function(int tid) {
    cout << "abcdefghijklmnopqrstuvwxyz" << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    const int cntThreads = 100000;
    thread t[cntThreads];

    for(int i = 0; i < cntThreads; ++i) {
        t[i] = thread(thread_function, i);
    }

    for(int i = 0; i < cntThreads; ++i) {
        t[i].join();
    }

    return 0;
}

위의 코드는 10만개의 스레드를 생성하고 있고 각 스레드는 7번 코드에서 정의한 thread_function 함수를 실행합니다. 17번 코드가 스레드를 생성하고 실행하는 코드로 첫번째 인자는 실행할 함수이고 두번째는 스레드의 id입니다. 그리고 21번 코드는 스레드가 완전히 종료될때까지 주 스레드를 대기시키는 join 함수입니다. 위의 코드를 실행해 보면 10만개의 스레드가 abc..... 문자열이 서로 뒤섞여 표시되는 것을 볼 수 있는데, 이를 위해 동기화를 해줄 필요가 있습니다. 다음 코드는 이러한 동기화를 위해 C++11에서 제공되는 std::mutex를 사용한 예제입니다.

#include "stdafx.h"
#include 
#include 
#include 

using namespace std;

mutex m;

void thread_function(int tid) {
    m.lock();

    cout << "abcdefghijklmnopqrstuvwxyz" << endl;

    m.unlock();
}

int _tmain(int argc, _TCHAR* argv[])
{
    const int cntThreads = 100000;
    thread t[cntThreads];

    for(int i = 0; i < cntThreads; ++i) {
        t[i] = thread(thread_function, i);
    }

    for(int i = 0; i < cntThreads; ++i) {
        t[i].join();
    }

    return 0;
}

변경된 부분은 8번 코드에서 동기화를 위한 mutex 객체를 하나를 정의했고 스레드 함수 내에서 abc.... 문자열을 표시하는 부분을 동기화 하기 위해 이 코드의 앞뒤에 mutex의 lock과 unlock 함수를 호출하고 있습니다. 이렇게 하면 이들 코드 사이에 있는 코드가 동기화가 되어 문자열이 뒤섞이지 않습니다.

[C++11] 정밀한 시간 측정을 위한 chrono

하드웨어의 발전으로 보다 정밀한 시간을 측정할 수 있게 되었고, 이를 위해 C++11에서는 chrono를 제공합니다. chrono를 이용하여 측정한 시간값의 정밀도는 나노(nano, 0.000000001)초라고 합니다. 아래는 코드는 어떠한 연산에 대한 소요 시간을 측정하는 경우로써 chrono를 사용한 코드입니다.

#include "stdafx.h"
#include 
#include 

using namespace std;
using namespace chrono;

int _tmain(int argc, _TCHAR* argv[])
{
    system_clock::time_point tp1 = system_clock::now();
	
    double v = 0;
    for(long i = 0; i < 100000000; i++) {
        v += 0.1;
    }

    system_clock::time_point tp2 = system_clock::now();

    nanoseconds t = tp2 - tp1;
    cout << "nanoseconds: " << t.count() << endl;
    cout << "seconds: " << t.count() / 1000000000.0 << endl;

    return 0;
}

실행 시간을 측정한 연산에 대한 코드는 12번 ~ 15번입니다. 이 코드 부분의 앞뒤로 chrono를 이용하여 시간을 측정하고 있습니다. 측정된 시간의 차이(17번 코드)를 통해 연산에 소요되는 시간을 알 수 있습니다. 시간 차이에 대한 단위는 nano이며 이를 초(second)로 변환하기 위해 21번 코드처럼 1000000000값으로 나누어 출력하고 있습니다.