3

私のコードが異常な出力を出したり、時にはセグメント エラーが発生したりする理由がわかりません (私の大学が盗作をチェックした場合に備えて、このコードは私が 08218722 で作成しました)。

コードはLinux Mint 14のC++で記述され、次のようにコンパイルされています。

g++ -o code.exe code.cpp -lpthread

で実行し./code.exeます。

このコードは、最大 1000000 個のランダムな文字ベクトル (文字 a、b、c、d、e、および f のみを使用) を生成し、ループして各文字の数をカウントすることになっています。これは、スレッドを追加する前にうまく機能しました (非スレッドとスレッド間の実行時間をテストするための割り当ての一部)。そこで、ベクトルに追加する 1000 文字を作成するように指示された 1000 個のスレッドを作成します。ここで何が間違っていますか?

更新-コードはまだいくつかのクレイジーな結果を出力しています-今では文字ではなく、ある種の正方形のボックスが表示されます

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <vector>
#include <algorithm>
#include <pthread.h>
#include <ctime>

using namespace std;

//Variable Declarations
const int length = 1000000; // length
const int packets = 1000; // packets length
const char chars[6] = {'a', 'b', 'c', 'd', 'e', 'f'}; // chars to choose
vector<char> charList(length); //vector of random charecter list
int charGroup[6] = {}; //stores char count
pthread_t threads[packets];



//Structure Declarations
struct dataStruct {
    int start;
    int end;
};

//Function Declarations
void *randomLetterGenerator(void * args); // Declaring function

// prints the vector
void outVector(char n)
{
    cout << n;
}

void GroupVector(char n)
{
   charGroup[n] = charGroup[n] + 1;
}

int main(){
        cout << "Creating a Random Char Array" << endl;
        cout << "using only letters ranging between a and f." << endl;
        //srand(time(NULL)); // sets the time seed
        clock_t start = clock();
        for(int i=0;i<length/packets;i++) {
            printf("\rPlease wait...%3d/%3d",i*packets,length);
            //Created in packets
            dataStruct ds;
            ds.start = i * (length/packets);
            ds.end = ds.start + (length/packets);
            pthread_create(&threads[i], NULL, randomLetterGenerator, (void *)&ds);
        }

        for(int i=0;i<length/packets;i++) {
            pthread_join(threads[i], NULL);
        }

        printf("\n"); //new line

        //prints out the new char list

        for_each(charList.begin(), charList.end(), outVector) ;

        printf("\n"); //new line

        //Counts and places in the correct array
        for_each(charList.begin(), charList.end(), GroupVector) ;

        int total = 0;

        for (int i = 0; i < 6; i++) {
            total += charGroup[chars[i]];
            cout << chars[i] << " = " << charGroup[chars[i]] << endl;
        }
        cout << "\nTotal: " << total << endl;
        clock_t ends = clock();
        cout << "Run Time :"
        << (double) (ends - start) / CLOCKS_PER_SEC << endl;
         pthread_exit(NULL);    
        return 0;   

}

void * randomLetterGenerator(void * datastruct){
    dataStruct ds = *((dataStruct *) datastruct);
    int start = ds.start;
    int end = ds.end;

     srand( time(NULL) );
    for(unsigned int c=start;c<end;c++){
        int i = (int) (rand() % 6);
        char rchar = chars[i];
        //--pthread_mutex_lock (&mutex);
        charList.at(c)= i;
        //--charList.push_back(rchar);  
        //--pthread_mutex_unlock (&mutex);  
    }
    pthread_exit(NULL);

}
4

2 に答える 2

3

ほとんどの場合、ロックがないためです。複数のスレッドが vector のような標準コンテナーに同時に書き込むことはできません。関数内で多数のスレッドが実行charList.push_back(rchar);されてrandomLetterGeneratorいる場合、これはまさに実行していることです。このコードを で囲む必要があります。mutex例:

pthread_mutex_t mutex;

void * randomLetterGenerator(void * datastruct)
{ 
    //Code as before
    //...
    //Lock the mutex
    charList.push_back(rchar);
    //Unlock the mutex
}
于 2013-01-04T03:32:34.603 に答える
3

ここで間違ったアプローチを使用しています。適切なサイズのベクトルを作成し、要素割り当てを使用して要素を入力する必要があります。

ベクターのpush_back関数を使用しても機能せず、ベクターの内部状態を変更する必要があり、スレッドセーフではないため、プログラムがクラッシュする可能性があります。ミューテックスを介してロックで囲んだ場合は問題なく動作しますが、並列処理のメリットを完全に無視してしまいます。

そのため、すでに必要な数のエントリを持つベクトルを作成し ( vector<char> lots_of_chars(length);)、アイテム割り当てを使用して各アイテムに割り当てます。各スレッドは、互いに踏みつけないように、ベクター内の異なるオフセットから開始する必要があります。

これを機能させるために使用する特定のコードを提供しますが、これは割り当てのように聞こえるので、自分で解決できるようにしましょう。

もう 1 つのスレッド セーフの問題があります。ここで実際に問題が発生することはありませんが、注意が必要です。randスレッドセーフではありません。連続する「乱数」を大量に生成するには、共有グローバル状態に依存します。ブーストまたは C++11 を使用しない限り、私が認識しているスレッドセーフな乱数生成に適したオプションはありません。ただし、C++11 を使用している場合は、pthreads の代わりに C++11s ビルドイン スレッド サポートを使用する必要があります。

この特定のケースでは、乱数生成が実際に乱数を生成することはそれほど重要ではありません。したがって、スレッドが乱数ジェネレーターを介して互いに踏みつけ、状態を繰り返し、同じシーケンスの乱数などを生成する場合、それは問題ありません。もちろん、それは最も可能性の高い結果です。randこの非スレッドセーフな方法での使用は、実際には未定義の動作であり、そのために何かが起こる可能性があります。

于 2013-01-04T03:37:19.147 に答える