2012-06-13 4 views
0

나는 아주 쉬운 질문이 있는데, 나는 대답을 온라인으로 찾을 수 없다. 나는 병합 정렬 함수를 만들었지 만 (비효율적 인 것은 확실하다), 여기에 스레드에 대해 물어 보려한다. Windows의 CreateThread 함수를 사용하여 스레드를 생성하여 지정된 배열의 간격을 정렬합니다. 모든 스레드가 완료되면 최종 결과를 위해 세그먼트를 병합합니다. 내가 마지막 병합을 구현하지 않았다는 것은 아직까지도 이상한 오류가 발생했기 때문에 스레드의 실수로 인한 것입니다. paraMSort를 친절하게 살펴볼 수 있다면 코드를 게시 할 것입니다. MergeSort.h 파일 전체를 게시하면 도우미 기능도 볼 수 있습니다. 때로는 코드가 완벽하게 컴파일되고 실행됩니다. 때로는 콘솔이 오류/예외없이 갑자기 닫힙니다. 배열의 다른 세그먼트 (다른 ​​메모리 위치 모두)에서 작업을 수행하기 때문에 뮤텍스 문제가 발생하지 않아야합니다. 아무도 잘못 본 것이 있습니까? 정말 고마워.Windows 글타래 (쓰레드) : Parallel Mergesort

추신. Windows CreateThread의 커널 수준입니까? 즉, 듀얼 코어 컴퓨터에서 2 개의 스레드를 만들면 별도의 코어에서 동시에 실행할 수 있습니까? 내 생각에 네,이 컴퓨터에서 2 번 스레드 (다른 테스트 예제 사용)로 같은 작업을 할 수 있기 때문입니다.

PPS. 또한 Boost.Thread를 사용하여 해결 된 병렬 처리 결과를 보았습니다. 윈도우 스레드 대신 부스트 스레드를 사용해야합니까? Boost에 대한 경험이 없습니다.

#include "Windows.h" 
#include <iostream> 
using namespace std; 

void insert_sort(int* A, int sA, int eA, int* B, int sB, int eB) 
{ 
    int value; 
    int iterator; 

    for(int i = sA + 1; i < eA; i++) 
    { 
     value = A[i]; // Grab the next value in the array 
     iterator = i - 1; 
     // Move this value left up the list until its in the right spot 
     while(iterator >= sA && value < A[iterator]) 
      A[iterator + 1] = A[iterator--]; 
     A[iterator + 1] = value; // Put value in its correct spot 
    } 
    for(int i = sA; i < eB; i++) 
    { 
     B[i] = A[i]; // Put results in B 
    } 
} 

void merge_func(int* a, int sa, int ea, int* b, int sb, int eb, int* c, int sc) 
{ 
    int i = sa, j = sb, k = sc; 

    while(i < ea && j < eb) 
     c[k++] = a[i] < b[j] ? a[i++] : b[j++]; 
    while(i < ea) 
     c[k++] = a[i++]; 
    while(j < eb) 
     c[k++] = b[j++]; 
} 

void msort_big(int* a, int* b, int s, int e, bool inA) 
{ 
    if(e-s < 4) 
    { 
     insert_sort(a, s, e, b, s, e); 
     return; // We sorted (A,s,e) into (B,s,e). 
    } 
    int m = (s + e)/2; 
    msort_big(a, b, s, m, !inA); 
    msort_big(a, b, m, e, !inA); 

    // If we want to merge in A, do it. Otherwise, merge in B 
    inA ? merge_func(b, s, m, b, m, e, a, s) : merge_func(a, s, m, a, m, e, b, s); 
} 

void msort(int* toBeSorted, int s, int e) 
// Sorts toBeSorted from [s, e+1), so just enter [s, e] and 
// the call to msort_big adds one. 
{ 
    int* b = new int[e - s + 1]; 
    msort_big(toBeSorted, b, s, e+1, true); 
    delete [] b; 
} 

template <class T> 
struct SortData_Send 
{ 
    T* data; 
    int start; 
    int end; 
}; 

DWORD WINAPI msort_para_callback(LPVOID lpParam) 
{ 
    SortData_Send<int> dat = *(SortData_Send<int>*)lpParam; 
    msort(dat.data, dat.start, dat.end); 
    cout << "done! " << endl; 
} 

int ceiling_func(double num) 
{ 
    int temp = (int)num; 

    if(num > (double)temp) 
    { 
     return temp + 1; 
    } 
    else 
    { 
     return temp; 
    } 
} 

void paraMSort(int* toBeSorted, int s, int e, int numThreads) 
{ 
    HANDLE threads[numThreads]; 
    DWORD threadIDs[numThreads]; 
    SortData_Send<int>* sent[numThreads]; 

    for(int i = 0; i < numThreads; i++) 
    { 
     // So for each thread, make an interval and pass the pointer to the array of ints. 
     // So for numThreads = 3 and array size of 0 to 99 (100), we have 0-32, 33-65, 66-100. 
     // 100 because sort function takes [start, end). 
     sent[i] = new SortData_Send<int>; 
     sent[i]->data = toBeSorted; 
     sent[i]->start = s + ceiling_func(double(i)*(double)e/double(numThreads)); 
     sent[i]->end = ceiling_func(double(i+1)*double(e)/double(numThreads)) + ((i == numThreads-1) ? 1 : -1); 
     threads[i] = CreateThread(NULL, 0, msort_para_callback, sent[i], 0, &threadIDs[i]); 
    } 
    WaitForMultipleObjects(numThreads, threads, true, INFINITE); 
    cout << "Done waiting!" <<endl; 

} 
+0

Windows 스레드가 아닌 알고리즘에 병렬 처리를 추가 할 때 OpenMP를 사용하는 것이 좋습니다. – Spo1ler

+0

또한 캐시 라인 공유 (cache line sharing)가있을 수 있습니다. 이는 응용 프로그램의 성능에 좋지 않습니다. – Spo1ler

+0

감사합니다. Spo1ler, OpenMP를 사용해 보겠습니다. 나는 확실히 휴대용/전문가가되고 싶습니다. 대부분의 좋은 컴파일러가 기본적으로 이것을 지원하는 것으로 보입니다. 그리고 나는 그것에 대해 알지도 못했습니다. 이것을 언급 해 주셔서 감사합니다! :) –

답변

0

's'를 가정하면 시작 지점 및 'E'는 스레드에 대한 종료 지점이 코드는이 경우 함수 무효 paraMSort에

sent[i]->start = s + ceiling_func(double(i)*(double)(e-s)/double(numThreads)); 
sent[i]->end = (i == numThreads-1) ? e : (s - 1 + ceiling_func(double(i+1)*(double)(e-s)/double(numThreads))); 

같은 안된다 (int * toBeSorted, int s, int e, int numThreads)의 값이 '0'이 아닌 값으로 호출되고 있습니까? 이로 인해 잘못된 섹션을 읽을 수 있습니다.

+0

아픈 수학 다시 확인, 그것을 볼 시간을내어 주셔서 감사합니다 :). 필자는 테스트 목적으로 만 s = 0으로 호출했습니다. 이것은 확실히 후에 버그 일 수있었습니다! –