편집 필터 기록

편집 필터 둘러보기 (처음 | 최근 필터의 바뀜 | 과거의 편집 검토하기 | 편집 필터 기록)
기록 8,767에 대한 자세한 정보

2015년 8월 10일 (월) 00:57: 다메즈마 (토론 | 기여)님이 사용자:다메즈마/C++11/02 멀티스레딩01 스레드클래스에서 "edit" 동작을 수행하여 필터 0이(가) 작동했습니다. 조치: 태그; 필터 설명: (검사)

편집에서 바뀐 내용

기존의 C/C++의 경우 멀티스레드 프로그래밍을 하기 위해서는 운영체제API를 호출하거나 외부라이브러리(OpenMP)을 써야 했습니다. 이번 C++11에서는 표준라이브러리로 멀티스레드 지원을 위한 클래스가 추가되었습니다.


thread헤더 파일를 포합시켜야 하며, 스레드의 진입함수에 매개 변수를 넣어 줄 수 있습니다.
std::thread(함수의 어드레스, 스레드의 진입점에 넣어줄 매개 변수...)
매개 변수의 경우, printf함수 처럼 인자 수을 바꿀 수 도있습니다.
스레드를 쓴다음, 정리하기 위해서는 detach메소드나 join메소드를 호출 해줘야 합니다.
스레드를 잠시 쉬게 하는, 윈도우의 Sleep함수와 동일한 역할을 하는 함수는  std::this_thread::sleep_for(std::chrono::seconds(초))입니다.
다음 코드는 두 개의  1000x1000행렬을 곱하는 코드입니다.
<source lang="cpp">
#include <iostream>
#include <thread>
#include <mutex>
#include <windows.h>
#include <array>
#include <stdlib.h>
#include <time.h>
    std::array<std::array<int,1000>,1000> a;
    std::array<std::array<int,1000>,1000> b;
    std::array<std::array<int,1000>,1000> c;
int main()
{
    srand(time(NULL));
    for(auto & i : a){
            for(auto & j : i){
                j = rand() % 5000;
            }
    }
    for(auto & i : b){
            for(auto & j : i){
                j = rand() % 5000;
            }
    }
    std::cout<<"시작!"<<std::endl;
    int startTick = GetTickCount();
    int endTick = 0;
    for(int i = 0; i < c.size() ; i++)
    {
        for(int j = 0; j < c[i].size() ; j++)
        {
            for(int k = 0; k < c.size(); k++)
            {
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }
    endTick = GetTickCount();
    std::cout<<"끝! 걸린 시간 총 "<<double(endTick - startTick)/1000.0<<"초"<<std::endl;
    return 0;
}
</source>
걸린 시간 50.875
== 멀티 스레드 베타1 ==
가장 동기화 락에 덜걸리게 설계한다.
<source lang="cpp">
#include <iostream>
#include <thread>
#include <mutex>
#include <array>
#include <stdlib.h>
#include <time.h>
#include <queue>
#include <stdio.h>
#include <windows.h>
struct Node{
    int i;
    int j;
};
struct ResultWorkNode{
    int i;
    int j;
    int r;
};
std::mutex g_queueMutex;
std::mutex g_result;
std::queue<Node> g_workQueue;
std::queue<ResultWorkNode> g_resultQueue;
std::array<std::array<int,1000>,1000> a;
std::array<std::array<int,1000>,1000> b;
std::array<std::array<int,1000>,1000> c;
int thread_func(){
    std::queue<Node> localQueue;
    std::queue<ResultWorkNode> localResQueue;
    while(g_workQueue.empty() == false){
//로컬 큐에 전역 큐에 있는 계산 해야 하는 것을 가져 온다.
        if(localQueue.empty())
        {
            g_queueMutex.lock();
            for(int i = 0 ; i < 5; i++){
                    if(g_workQueue.empty()){
                        break;
                    }
                    localQueue.push(g_workQueue.front());
                    g_workQueue.pop();
            }
            g_queueMutex.unlock();
        }
        else if(g_queueMutex.try_lock())
        {
            for(int i = 0 ; i < 5; i++){
                    if(g_workQueue.empty()){
                        break;
                    }
                    localQueue.push(g_workQueue.front());
                    g_workQueue.pop();
            }
            g_queueMutex.unlock();
        }
//이제 로컬 큐에 있는 것을 계산한다.
        while(localQueue.empty() == false){
            Node node = localQueue.front();
            localQueue.pop();
            int res = 0;
            for(int i = 0 ; i < 1000 ; i++){
                    res += a[node.i][i] * b[i][node.j];
            }
            //
            ResultWorkNode r;
            r.i = node.i;
            r.j = node.j;
            r.r = res;
            //c[node.i][node.j] = res;
            localResQueue.push(r);
        }
        if(g_result.try_lock()){
            while(localQueue.empty() == false){
                g_resultQueue.push(localResQueue.front());
                localResQueue.pop();
            }
            g_result.unlock();
        }
    }
    if(localResQueue.empty() == false){
        g_result.lock();
        while(localResQueue.empty() == false){
            g_resultQueue.push(localResQueue.front());
            localResQueue.pop();
        }
        g_result.unlock();
    }
    return 0;
}
int main()
{
    srand(time(NULL));
    for(int i = 0 ; i < 1000; i++){
            for(int j = 0 ; j < 1000; j++){
                a[i][j] = rand() % 10 + 1;
                b[i][j] = rand() % 10 + 1;
            }
    }
    for(int i = 0; i < c.size() ; i++)
    {
        for(int j = 0; j < c[i].size() ; j++)
        {
            Node node;
            node.i = i;
            node.j = j;
            g_workQueue.push(node);
        }
    }
    std::cout<<"시작!"<<std::endl;
    int startTick = GetTickCount();
    int endTick = 0;
    std::thread a(thread_func);
    std::thread b(thread_func);
    a.join();
    b.join();
    while(g_resultQueue.empty() == false){
        ResultWorkNode n = g_resultQueue.front();
        g_resultQueue.pop();
        c[n.i][n.j] = n.r;
    }
    endTick = GetTickCount();
    FILE * fp = fopen("./res.txt","w+");
    for(auto & i : c){
        for(auto & cell : i){
            fprintf(fp,"%7d ",cell);
        }
        fprintf(fp,"\n");
    }
    fclose(fp);
    std::cout<<"끝! 걸린 시간 총 "<<double(endTick - startTick)/1000.0<<"초"<<std::endl;
    return 0;
}
</source>
걸린 시간: 17초
TDM-GCC O2 최적화시 : 4초, 2차 실행시 CPU실행으로 인해 2초...
== 멀티 스레드 베타2 ==

명령 변수

변수
사용자의 편집 수 (user_editcount)
1057
사용자 계정 이름 (user_name)
'다메즈마'
사용자 계정 만든 후 지난 시간 (user_age)
9945589
user_mobile
false
문서 ID (page_id)
32557
문서 이름공간 (page_namespace)
2
(이름공간을 뺀) 문서 제목 (page_title)
'다메즈마/C++11/02 멀티스레딩01 스레드클래스'
전체 문서 제목 (page_prefixedtitle)
'사용자:다메즈마/C++11/02 멀티스레딩01 스레드클래스'
동작 (action)
'edit'
편집 요약/이유 (summary)
''
사소한 편집으로 표시할지의 여부 (더 이상 쓰이지 않음) (minor_edit)
false
편집 전 과거 문서의 위키텍스트 (old_wikitext)
'기존의 C/C++의 경우 멀티스레드 프로그래밍을 하기 위해서는 운영체제API를 호출하거나 외부라이브러리(OpenMP)을 써야 했습니다. 이번 C++11에서는 표준라이브러리로 멀티스레드 지원을 위한 클래스가 추가되었습니다. thread헤더 파일를 포합시켜야 하며, 스레드의 진입함수에 매개 변수를 넣어 줄 수 있습니다. std::thread(함수의 어드레스, 스레드의 진입점에 넣어줄 매개 변수...) 매개 변수의 경우, printf함수 처럼 인자 수을 바꿀 수 도있습니다. 스레드를 쓴다음, 정리하기 위해서는 detach메소드나 join메소드를 호출 해줘야 합니다. 스레드를 잠시 쉬게 하는, 윈도우의 Sleep함수와 동일한 역할을 하는 함수는 std::this_thread::sleep_for(std::chrono::seconds(초))입니다. 다음 코드는 두 개의 1000x1000행렬을 곱하는 코드입니다. <source lang="cpp"> #include <iostream> #include <thread> #include <mutex> #include <windows.h> #include <array> #include <stdlib.h> #include <time.h> std::array<std::array<int,1000>,1000> a; std::array<std::array<int,1000>,1000> b; std::array<std::array<int,1000>,1000> c; int main() { srand(time(NULL)); for(auto & i : a){ for(auto & j : i){ j = rand() % 5000; } } for(auto & i : b){ for(auto & j : i){ j = rand() % 5000; } } std::cout<<"시작!"<<std::endl; int startTick = GetTickCount(); int endTick = 0; for(int i = 0; i < c.size() ; i++) { for(int j = 0; j < c[i].size() ; j++) { for(int k = 0; k < c.size(); k++) { c[i][j] += a[i][k] * b[k][j]; } } } endTick = GetTickCount(); std::cout<<"끝! 걸린 시간 총 "<<double(endTick - startTick)/1000.0<<"초"<<std::endl; return 0; } </source> 걸린 시간 50.875 == 멀티 스레드 베타1 == 가장 동기화 락에 덜걸리게 설계한다. <source lang="cpp"> #include <iostream> #include <thread> #include <mutex> #include <array> #include <stdlib.h> #include <time.h> #include <queue> #include <stdio.h> #include <windows.h> struct Node{ int i; int j; }; struct ResultWorkNode{ int i; int j; int r; }; std::mutex g_queueMutex; std::mutex g_result; std::queue<Node> g_workQueue; std::queue<ResultWorkNode> g_resultQueue; std::array<std::array<int,1000>,1000> a; std::array<std::array<int,1000>,1000> b; std::array<std::array<int,1000>,1000> c; int thread_func(){ std::queue<Node> localQueue; std::queue<ResultWorkNode> localResQueue; while(g_workQueue.empty() == false){ //로컬 큐에 전역 큐에 있는 계산 해야 하는 것을 가져 온다. if(localQueue.empty()) { g_queueMutex.lock(); for(int i = 0 ; i < 5; i++){ if(g_workQueue.empty()){ break; } localQueue.push(g_workQueue.front()); g_workQueue.pop(); } g_queueMutex.unlock(); } else if(g_queueMutex.try_lock()) { for(int i = 0 ; i < 5; i++){ if(g_workQueue.empty()){ break; } localQueue.push(g_workQueue.front()); g_workQueue.pop(); } g_queueMutex.unlock(); } //이제 로컬 큐에 있는 것을 계산한다. while(localQueue.empty() == false){ Node node = localQueue.front(); localQueue.pop(); int res = 0; for(int i = 0 ; i < 1000 ; i++){ res += a[node.i][i] * b[i][node.j]; } // ResultWorkNode r; r.i = node.i; r.j = node.j; r.r = res; //c[node.i][node.j] = res; localResQueue.push(r); } if(g_result.try_lock()){ while(localQueue.empty() == false){ g_resultQueue.push(localResQueue.front()); localResQueue.pop(); } g_result.unlock(); } } if(localResQueue.empty() == false){ g_result.lock(); while(localResQueue.empty() == false){ g_resultQueue.push(localResQueue.front()); localResQueue.pop(); } g_result.unlock(); } return 0; } int main() { srand(time(NULL)); for(int i = 0 ; i < 1000; i++){ for(int j = 0 ; j < 1000; j++){ a[i][j] = rand() % 10 + 1; b[i][j] = rand() % 10 + 1; } } for(int i = 0; i < c.size() ; i++) { for(int j = 0; j < c[i].size() ; j++) { Node node; node.i = i; node.j = j; g_workQueue.push(node); } } std::cout<<"시작!"<<std::endl; int startTick = GetTickCount(); int endTick = 0; std::thread a(thread_func); std::thread b(thread_func); a.join(); b.join(); while(g_resultQueue.empty() == false){ ResultWorkNode n = g_resultQueue.front(); g_resultQueue.pop(); c[n.i][n.j] = n.r; } endTick = GetTickCount(); FILE * fp = fopen("./res.txt","w+"); for(auto & i : c){ for(auto & cell : i){ fprintf(fp,"%7d ",cell); } fprintf(fp,"\n"); } fclose(fp); std::cout<<"끝! 걸린 시간 총 "<<double(endTick - startTick)/1000.0<<"초"<<std::endl; return 0; } </source> 걸린 시간: 17초 TDM-GCC O2 최적화시 : 4초, 2차 실행시 CPU실행으로 인해 2초... == 멀티 스레드 베타2 =='
편집 후 새 문서의 위키텍스트 (new_wikitext)
''
편집 전후의 차이 (edit_diff)
'@@ -1,209 +1 @@ -기존의 C/C++의 경우 멀티스레드 프로그래밍을 하기 위해서는 운영체제API를 호출하거나 외부라이브러리(OpenMP)을 써야 했습니다. 이번 C++11에서는 표준라이브러리로 멀티스레드 지원을 위한 클래스가 추가되었습니다. -thread헤더 파일를 포합시켜야 하며, 스레드의 진입함수에 매개 변수를 넣어 줄 수 있습니다. -std::thread(함수의 어드레스, 스레드의 진입점에 넣어줄 매개 변수...) -매개 변수의 경우, printf함수 처럼 인자 수을 바꿀 수 도있습니다. - -스레드를 쓴다음, 정리하기 위해서는 detach메소드나 join메소드를 호출 해줘야 합니다. - -스레드를 잠시 쉬게 하는, 윈도우의 Sleep함수와 동일한 역할을 하는 함수는 std::this_thread::sleep_for(std::chrono::seconds(초))입니다. - -다음 코드는 두 개의 1000x1000행렬을 곱하는 코드입니다. -<source lang="cpp"> -#include <iostream> -#include <thread> -#include <mutex> -#include <windows.h> -#include <array> -#include <stdlib.h> -#include <time.h> - std::array<std::array<int,1000>,1000> a; - std::array<std::array<int,1000>,1000> b; - std::array<std::array<int,1000>,1000> c; -int main() -{ - - - srand(time(NULL)); - for(auto & i : a){ - for(auto & j : i){ - j = rand() % 5000; - } - } - for(auto & i : b){ - for(auto & j : i){ - j = rand() % 5000; - } - } - std::cout<<"시작!"<<std::endl; - int startTick = GetTickCount(); - int endTick = 0; - for(int i = 0; i < c.size() ; i++) - { - for(int j = 0; j < c[i].size() ; j++) - { - for(int k = 0; k < c.size(); k++) - { - - c[i][j] += a[i][k] * b[k][j]; - } - } - } - endTick = GetTickCount(); - std::cout<<"끝! 걸린 시간 총 "<<double(endTick - startTick)/1000.0<<"초"<<std::endl; - return 0; -} - -</source> -걸린 시간 50.875 -== 멀티 스레드 베타1 == -가장 동기화 락에 덜걸리게 설계한다. -<source lang="cpp"> -#include <iostream> -#include <thread> -#include <mutex> -#include <array> -#include <stdlib.h> -#include <time.h> -#include <queue> -#include <stdio.h> -#include <windows.h> -struct Node{ - int i; - int j; -}; -struct ResultWorkNode{ - int i; - int j; - int r; -}; - -std::mutex g_queueMutex; -std::mutex g_result; -std::queue<Node> g_workQueue; -std::queue<ResultWorkNode> g_resultQueue; - -std::array<std::array<int,1000>,1000> a; -std::array<std::array<int,1000>,1000> b; -std::array<std::array<int,1000>,1000> c; - -int thread_func(){ - std::queue<Node> localQueue; - std::queue<ResultWorkNode> localResQueue; - while(g_workQueue.empty() == false){ -//로컬 큐에 전역 큐에 있는 계산 해야 하는 것을 가져 온다. - if(localQueue.empty()) - { - g_queueMutex.lock(); - for(int i = 0 ; i < 5; i++){ - if(g_workQueue.empty()){ - break; - } - localQueue.push(g_workQueue.front()); - g_workQueue.pop(); - } - g_queueMutex.unlock(); - } - else if(g_queueMutex.try_lock()) - { - for(int i = 0 ; i < 5; i++){ - if(g_workQueue.empty()){ - break; - } - localQueue.push(g_workQueue.front()); - g_workQueue.pop(); - } - g_queueMutex.unlock(); - } -//이제 로컬 큐에 있는 것을 계산한다. - while(localQueue.empty() == false){ - Node node = localQueue.front(); - localQueue.pop(); - int res = 0; - for(int i = 0 ; i < 1000 ; i++){ - res += a[node.i][i] * b[i][node.j]; - } - // - ResultWorkNode r; - r.i = node.i; - r.j = node.j; - r.r = res; - //c[node.i][node.j] = res; - localResQueue.push(r); - } - if(g_result.try_lock()){ - while(localQueue.empty() == false){ - g_resultQueue.push(localResQueue.front()); - localResQueue.pop(); - } - g_result.unlock(); - } - - } - if(localResQueue.empty() == false){ - g_result.lock(); - while(localResQueue.empty() == false){ - g_resultQueue.push(localResQueue.front()); - localResQueue.pop(); - } - g_result.unlock(); - } - return 0; -} - - - -int main() -{ - - - srand(time(NULL)); - for(int i = 0 ; i < 1000; i++){ - for(int j = 0 ; j < 1000; j++){ - a[i][j] = rand() % 10 + 1; - b[i][j] = rand() % 10 + 1; - } - } - - for(int i = 0; i < c.size() ; i++) - { - for(int j = 0; j < c[i].size() ; j++) - { - Node node; - node.i = i; - node.j = j; - - g_workQueue.push(node); - } - } - - std::cout<<"시작!"<<std::endl; - int startTick = GetTickCount(); - int endTick = 0; - std::thread a(thread_func); - std::thread b(thread_func); - a.join(); - b.join(); - while(g_resultQueue.empty() == false){ - ResultWorkNode n = g_resultQueue.front(); - g_resultQueue.pop(); - c[n.i][n.j] = n.r; - } - - endTick = GetTickCount(); - FILE * fp = fopen("./res.txt","w+"); - for(auto & i : c){ - for(auto & cell : i){ - fprintf(fp,"%7d ",cell); - } - fprintf(fp,"\n"); - } - fclose(fp); - std::cout<<"끝! 걸린 시간 총 "<<double(endTick - startTick)/1000.0<<"초"<<std::endl; - return 0; -} -</source> - -걸린 시간: 17초 -TDM-GCC O2 최적화시 : 4초, 2차 실행시 CPU실행으로 인해 2초... -== 멀티 스레드 베타2 == '
새 문서 크기 (new_size)
0
편집 중 추가된 줄 (added_lines)
[]
편집이 토르 끝 노드를 통해 바뀌었는 지의 여부 (tor_exit_node)
0
바뀐 시점의 유닉스 시간 기록 (timestamp)
1439135849