我正在创建一个读取矩阵文件的程序。我将这些矩阵存储在一个结构中,其中包含一个包含矩阵值数组的结构数组(例如: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 对。
我还应该注意,我的程序在不使用线程时运行良好,并且一次只创建一个线程并在创建新线程之前等待它完成。
这是一个需要几个小时才能完成的家庭作业(我已经为此工作了一周,刚刚通过了其他一些路障),所以任何帮助都将不胜感激!谢谢!