簡體   English   中英

在循環中創建pthread並傳遞遞增的參數,線程沒有使用正確的參數值

[英]creating pthreads in loop and passing incremented arguments, threads are not using the correct argument values

我正在創建一個讀入矩陣文件的程序。 我將這些矩陣存儲在一個結構中,該結構包含一個包含矩陣值數組的結構數組(例如: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;    

我的runner函數,即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);
}

printf()語句5行到runner是我打印傳遞給函數的值,它們並不總是匹配。 以下是該程序的一些輸出:

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開頭的行是在main函數的for循環中打印的行。 它們正是我所期望的。 它們被傳遞給運行器函數,它們再次被傳遞,但正如您所看到的,某些值被跳過,而其他值則被復制。 在2個不同的輸出中,0 =設置,1 =行,因此應該有一個匹配每個0/1對的一對/每對。

我還應該注意,我的程序在不使用線程時工作得很好,而且在創建新線程之前,一次只創建一個線程並等待它完成。

這是幾個小時內做的家庭作業(我已經工作了一個星期,剛剛通過其他一些路障),所以任何幫助都將非常感謝! 謝謝!

您不能使用單個數組將值傳遞到多個線程,因為每個線程都在讀取相同的數組。

為了更好地工作,創建一個包含每個線程所需的所有數據的結構。 然后創建一個結構數組,每個線程一個數組條目。 將每個線程傳遞給指向其中一個結構的指針。

這樣每個線程都可以訪問自己的信息,不會讀取或寫入另一個線程的信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM