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;    

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

runner 中的 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 = 集合和 1 = 行,因此应该有一个集合/行对匹配每个 0/1 对。

我还应该注意,我的程序在不使用线程时运行良好,并且一次只创建一个线程并在创建新线程之前等待它完成。

这是一个需要几个小时才能完成的家庭作业(我已经为此工作了一周,刚刚通过了其他一些路障),所以任何帮助都将不胜感激!谢谢!

4

1 回答 1

3

您不能使用单个数组将值传递给多个线程,因为每个线程都在读取同一个数组。

为了使这项工作更好地创建一个包含每个线程所需的所有数据的结构。然后制作一个由这些结构组成的数组,每个线程都有一个数组条目。向每个线程传递一个指向其中一个结构的指针。

这样每个线程都可以访问自己的信息,并且不会读取或写入另一个线程的信息。

于 2013-09-26T00:38:51.810 回答