0

できれば非常に簡単な質問がありますが、オンラインで答えを見つけることができません。私はマージソート機能を作成しました(これは確かに非効率的です)が、スレッドについて尋ねるためにここにいます。Windows の CreateThread 関数を使用してスレッドを生成し、特定の配列の間隔を並べ替えています。すべてのスレッドが終了したら、最終結果のためにセグメントをマージします。スレッドのばかげた間違いによる奇妙なエラーが発生するため、最終的なマージはまだ実装していません。親切にparaMSortを見ていただければ、私のコードを投稿します。ヘルパー関数も確認できるように、MergeSort.h ファイル全体を投稿します。場合によっては、コードが完全にコンパイルおよび実行されることがあります。エラーや例外が発生することなく、コンソールが突然終了することがあります。配列の異なるセグメントで操作を行っているため、ミューテックスの問題は発生しないはずです(完全に異なるメモリ位置)。誰かが何か間違っていると思いますか?本当にありがとう。

PS。Windows CreateThread のカーネル レベルですか? つまり、デュアル コア コンピュータで 2 つのスレッドを作成した場合、それらは別々のコアで同時に実行できますか? このコンピューターでは、2 つのスレッドで 1/2 の時間で同じ作業を実行できるため (別のテスト例を使用)、私はそう考えています。

PPS。また、Boost.Thread を使用して解決された並列処理の回答も見ました。Windows スレッドの代わりにブースト スレッドを使用する必要がありますか? ブーストの経験がありません。

#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;

}
4

1 に答える 1

0

「s」がスレッドの開始点で「e」がスレッドの終了点であると仮定すると、コードは次のようになるべきではありません

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)));

これは、関数void paraMSort(int* toBeSorted, int s, int e, int numThreads)が 0 に等しくない 's' の値で呼び出されている場合です。これにより、メモリの間違ったセクションを読み取る可能性があります。

于 2012-06-13T16:56:34.060 に答える