1

行列のファイルを読み込むプログラムを作成しています。これらの行列を、行列値の配列を含む構造体の配列を持つ構造体に格納します (例: matrixArray.array -> matrix.array)。次に、2 つの行列の各行の積を計算する複数のスレッドを作成します。pthread_create() で引数として渡されるカウンターを作成しました。これは、使用するマトリックスと、それらのマトリックスのどの行をスレッドに通知するかを示します。pthread_create() を呼び出すループでこのカウンターの結果を出力していますが、取得している結果は正しいものです。ただし、関数 pthread_create() 呼び出し内の値も出力していますが、値が常に一致するとは限りません。一部の数字をスキップし、他の数字を複製します。

これが私の主な機能です:

int main(int argc, char *argv[]) {
    pthread_t * tid; /* the thread identifier */
    pthread_attr_t attr; /* set of attributes for the thread */
    int i; // Counter
    int aIndex; // Index of the current 'A' matrix being multiplied.
    int rows,cols;
    int array[2];

    // Check to make sure we have the correct number of arguments supplied
    // when running the program.
    if(argc < 1){
            printf("Error: You did not provide the correct number of arguments.\n\n");
            return 0;
    }

    // Read the file and create the matrices
    readFile();

    // Get the default attributes
    pthread_attr_init(&attr);

    // Initialize the mutex lock
    pthread_mutex_init(&lock, NULL);

    // Set the current set to be mutliplied to 1
    currentSet = 1;

    // Allocate size of tid array based on number of threads
    tid = malloc(threads * sizeof(pthread_t));

    // Create the threads.
    for(i = 0; i < threads; i++){
            pthread_mutex_lock(&lock); // Lock the global variable so no other threads can access it
                    aIndex = ((currentSet * 2) - 2);
                    array[0] = currentSet;
                    array[1] = mtx.array[aIndex].multRow;
          //pthread_mutex_unlock(&lock); // Unlock the global variable so other threads can access it.

          // This prints the values stored in array. Array is passed inside pthread_create
          // 0 is the set of matrices that are to be multiplied together, with each
          // set containing 2 matrices, an A matrix and a B matrix.  
          // 1 represents the row in the A matrix that should be multiplied with matrix B
          printf("0 = %i, 1 = %i aIndex = %i\n",array[0],array[1],aIndex);

            pthread_create(&tid[i], &attr, runner, array);

            // Increment currentSet when the current row evalutated
            // in the current set is equal to the total number of rows available.

          //pthread_mutex_lock(&lock); // Lock the global variable so no other threads can access it.
                    mtx.array[aIndex].multRow++;

                    if(mtx.array[aIndex].multRow == mtx.array[aIndex].rows){
                            currentSet++;
                    }
            pthread_mutex_unlock(&lock); // Unlock the global variable so other threads can access it.

    }

    // Wait for threads to finish
    for(i = 0; i < threads; i++){
            pthread_join(tid[i], NULL);
    }

    // Print the matrices
    printMatrices();


    // Clean up the mutex when we are done with it.
    pthread_mutex_destroy(&lock);

    exit(0);

} // End of main()

mtx は、次のように定義された行列構造体の配列を含む matrixArray 構造体です。

typedef struct matrix {
    int rows;
    int cols;
    volatile int multRow; // The "MULTIPLIED ROW" This is for determing which row the current thread needs to use for multiplication. This only applies for Matrix A in each set.
    int size;
    int set; // This is for which set the matrix belongs to.
    char letter; // This is for labeling the matrices A B and C
    int * array;
    unsigned int * threadID; // Array containing the thread ids that are used to create the result
} matrix;

typedef struct matrixArray {
    int size;
    matrix * array;
} matrixArray;    

pthread_create が呼び出す関数である私のランナー関数は、次のように定義されています。

void *runner(void *param) {
    int * array = (int*)param;
    int pSet = array[0];
    int multRow = array[1];
    unsigned int threadID = (unsigned int)pthread_self();
printf("set = %i row = %i worker thread = %u\n",pSet,multRow,(unsigned int)pthread_self());
    // Do the matrix multiplication for a single row

    // The matrices are stored globally, so we do not need to pass that data.
    // However, we do want to pass in a reference to which matrices we want to
    // multiply.

    // The matrices we are dealing with are ((pSet * 2) - 2) and ((pSet * 2) - 1)
    // Need to create a new matrix C that will store the result of the matrix multiplication
    int rows, cols; // The dimensions of the matrix C.
    int aIndex, bIndex, cIndex; // The index of the matrices in the array.
    int i, r, c; // Counters
    int result; // This stores the result of the multiplication
    int aValueIndex, bValueIndex, cValueIndex; // These store the index of the value to be multiplied in each matrix

    aIndex = ((pSet * 2) - 2);
    bIndex = ((pSet * 2) - 1);

    pthread_mutex_lock(&lock); // Lock the global variables so no other thread can access it.
            rows = mtx.array[aIndex].rows;
            cols = mtx.array[bIndex].cols;

            // First we need to check if the matrix C for this set has been created.
            for(i = 0; i < mtxResults.size; i++){
                    if(mtxResults.array[i].set == pSet){
//printf("Found Set %i\n",i);
                            cIndex = i; // Store the index to this matrix
                            break;
                    }
            }

            // Now it is time to multiply the matrix row
            for (c = 0; c < cols; c++){
                    for (r = 0; r < mtx.array[bIndex].rows; r++){
                            // Need to calculate the location of the values we want to multiply
                            // Value in matrix A is going to be the current row 'r' from the 
                            // counter plus the current row being evaluated by this thread * the
                            // total number of columns of matrix A. 
                            // Value in matrix B is 'c' + (r * total number of columns in B)
                            // Multiply the values at those two locations and add them to the 
                            // running result.
                            //aValueIndex = r + (mtx.array[aIndex].multRow * mtx.array[aIndex].cols);
                            aValueIndex = r + (multRow * mtx.array[aIndex].cols);
                            bValueIndex = c + (r * mtx.array[bIndex].cols);
                            result = result + (mtx.array[aIndex].array[aValueIndex] * mtx.array[bIndex].array[bValueIndex]);
                    }
                    // Now place the value in the C matrix after calculating the location
                    // to place the value.
                    //cValueIndex = c + (mtx.array[aIndex].multRow * mtx.array[bIndex].cols);
                    cValueIndex = c + (multRow * mtx.array[bIndex].cols);
                    mtxResults.array[cIndex].array[cValueIndex] = result;

                    // Reset result
                    result = 0;
            }

            // Store the threadID in the result matrix
            mtxResults.array[cIndex].threadID[mtx.array[aIndex].multRow] = threadID;

      pthread_mutex_unlock(&lock); // Unlock the global variables so other threads can access it.

    pthread_exit(0);
}

runner の 5 行目の printf() ステートメントは、関数に渡された値を出力している場所であり、常に一致するとは限りません。プログラムの出力は次のとおりです。

0 = 1, 1 = 0 aIndex = 0
0 = 1, 1 = 1 aIndex = 0
0 = 1, 1 = 2 aIndex = 0
0 = 2, 1 = 0 aIndex = 2
0 = 2, 1 = 1 aIndex = 2
0 = 2, 1 = 2 aIndex = 2
0 = 2, 1 = 3 aIndex = 2
0 = 3, 1 = 0 aIndex = 4
set = 3 row = 0 worker thread = 3913365824
0 = 3, 1 = 1 aIndex = 4
0 = 3, 1 = 2 aIndex = 4
0 = 3, 1 = 3 aIndex = 4
0 = 3, 1 = 4 aIndex = 4
0 = 4, 1 = 0 aIndex = 6
0 = 4, 1 = 1 aIndex = 6
0 = 4, 1 = 2 aIndex = 6
set = 4 row = 2 worker thread = 3923855680
set = 4 row = 2 worker thread = 3934345536
set = 4 row = 2 worker thread = 3944835392
set = 4 row = 2 worker thread = 3955325248
set = 4 row = 2 worker thread = 3965815104
set = 4 row = 2 worker thread = 3976304960
set = 4 row = 2 worker thread = 3986794816
set = 4 row = 2 worker thread = 3997284672
set = 4 row = 2 worker thread = 4007774528
set = 4 row = 2 worker thread = 4018264384
set = 4 row = 2 worker thread = 4028754240
set = 4 row = 2 worker thread = 4039244096
set = 4 row = 2 worker thread = 4049733952
set = 4 row = 2 worker thread = 4060223808
0 = 4, 1 = 3 aIndex = 6
0 = 4, 1 = 4 aIndex = 6
0 = 4, 1 = 5 aIndex = 6
0 = 4, 1 = 6 aIndex = 6
0 = 4, 1 = 7 aIndex = 6
0 = 4, 1 = 8 aIndex = 6
0 = 4, 1 = 9 aIndex = 6
set = 4 row = 9 worker thread = 4070713664
set = 4 row = 9 worker thread = 4081203520
set = 4 row = 9 worker thread = 4091693376
set = 4 row = 9 worker thread = 4102183232
set = 4 row = 9 worker thread = 4112673088
set = 4 row = 9 worker thread = 4123162944
set = 4 row = 9 worker thread = 4133652800
0 = 5, 1 = 0 aIndex = 8
0 = 5, 1 = 1 aIndex = 8
0 = 5, 1 = 2 aIndex = 8
0 = 5, 1 = 3 aIndex = 8
0 = 5, 1 = 4 aIndex = 8
0 = 5, 1 = 5 aIndex = 8
0 = 5, 1 = 6 aIndex = 8
set = 5 row = 6 worker thread = 4144142656
set = 5 row = 6 worker thread = 4154632512
set = 5 row = 6 worker thread = 4165122368
set = 5 row = 6 worker thread = 4175612224
set = 5 row = 6 worker thread = 4186102080
set = 5 row = 6 worker thread = 4196591936
set = 5 row = 6 worker thread = 4207081792
0 = 6, 1 = 0 aIndex = 10
0 = 6, 1 = 1 aIndex = 10
0 = 6, 1 = 2 aIndex = 10
0 = 6, 1 = 3 aIndex = 10
set = 6 row = 3 worker thread = 4217571648
set = 6 row = 3 worker thread = 4249041216
set = 6 row = 3 worker thread = 4238551360
set = 6 row = 3 worker thread = 4228061504

0 で始まる行は、メイン関数の for ループで出力される行です。彼らはまさに私が期待しているものです。それらはランナー関数に渡され、そこで再び渡されますが、ご覧のとおり、一部の値はスキップされ、他の値は重複しています。2 つの異なる出力では、0 = セットおよび 1 = 行であるため、各 0/1 ペアに一致する 1 つのセット/行ペアが存在するはずです。

また、スレッドを使用していないとき、および一度に 1 つのスレッドのみを作成し、新しいスレッドを作成する前にスレッドが終了するのを待っているときも、私のプログラムは完全に機能したことに注意してください。

これは宿題で、数時間で完了します (私はこれに 1 週​​間取り組んでいて、他のいくつかの障害を乗り越えました)、どんな助けも大歓迎です! ありがとうございました!

4

1 に答える 1

3

すべてのスレッドが同じ配列を読み取るため、1 つの配列を使用して複数のスレッドに値を渡すことはできません。

これをうまく機能させるには、各スレッドが必要とするすべてのデータを含む構造体を作成します。次に、これらの構造体の配列を作成し、スレッドごとに 1 つの配列エントリを作成します。これらの構造体の 1 つへのポインターを各スレッドに渡します。

そうすれば、各スレッドは独自の情報にアクセスでき、別のスレッドの情報を読み書きすることはありません。

于 2013-09-26T00:38:51.810 に答える