2013-09-26 22 views
1

我正在創建一個讀取矩陣文件的程序。我將這些矩陣存儲在一個包含矩陣值數組結構數組的結構中(例如:matrixArray.array - > matrix.array)。然後創建多個線程,計算2個矩陣的每行的乘積。我創建了一個作爲pthread_create()中的參數傳遞的計數器,該計數器告訴線程要使用哪些矩陣以及這些矩陣中的哪一行。我在調用pthread_create()的循環中打印出這個計數器的結果,我得到的結果是正確的。但是,我也在函數pthread_create()調用中打印值,並且這些值並不總是匹配。它會跳過一些數字,並會複製其他數字。在循環中創建pthreads並傳遞遞增的參數,線程沒有使用正確的參數值

這是我的主要功能:

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

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

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循環中打印的行。他們正是我期望他們的。它們被傳遞給runner函數,在那裏它們被再次傳遞,但正如你所看到的,一些值被跳過,而另一些則被重複。在2個不同的輸出中,0 = set和1 = row,所以應該有一個set/row pair匹配每個0/1對。

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

這是幾個小時內完成的家庭作業任務(我一直在爲此工作一週,剛剛通過了一些其他路障),所以任何幫助將不勝感激!謝謝!

回答

3

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

爲了使這個工作更好地創建一個結構,其中包含每個線程所需的所有數據。然後創建這些結構的數組,每個線程都有一個數組入口。將每個線程傳遞給其中一個結構體的指針。

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

+0

這樣做。非常感謝!!!你是一個拯救生命的人! :) – Jason247