【发布时间】:2014-07-21 20:39:48
【问题描述】:
我写了一个并行 pthreads 程序来计算乘积的列和范数 两个 n*n 大小的矩阵。右矩阵是垂直分割的。用户输入矩阵大小 n 和线程数(p),以便:
- pthreads 参与并行计算。
- 采用矩阵乘法的一维并行算法:
- 右矩阵在一维上被划分为p个相等的切片(A*B,然后B被划分为p个切片)
- 分区和线程之间存在一对一的映射
- 每个线程负责计算结果矩阵的相应切片
代码:
double *A;
double *B;
double *C;
int n;
double matrix_norm;
typedef struct {
double *b;
double *c;
int num_of_columns;
pthread_mutex_t *mutex;
} matrix_slice;
void *matrix_slice_multiply(void *arg){
matrix_slice *slice = arg;
int i, j;
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, n, slice->num_of_columns, n, 1.0, A, n, slice->b, n, 0.0, slice->c, n);
// compute column norm of each slice
double slice_norm = 0.0;
for(j = 0; j < slice->num_of_columns; j++) {
double column_sum=0.;
for(i = 0; i < n; i++)
column_sum += *(slice->c + i * n + j);
if(column_sum>slice_norm)
slice_norm=column_sum;
}
pthread_mutex_lock(slice->mutex);
if (slice_norm>matrix_norm)
matrix_norm=slice_norm;
pthread_mutex_unlock(slice->mutex);
pthread_exit(NULL);
}
int main(void) {
int num_of_thrds, num_of_columns_per_slice;
pthread_t *working_thread;
matrix_slice *slice;
pthread_mutex_t *mutex;
int i = 0;
printf ("Please enter matrix dimension n : ");
scanf("%d", &n);
printf ("Please enter number of threads : ");
scanf("%d", &num_of_thrds);
while (num_of_thrds > n) {
printf("number of threads must not be greater than matrix dimension\n");
printf ("Please enter number of threads : ");
scanf("%d", &num_of_thrds);
}
// allocate memory for the matrices
///////////////////// Matrix A //////////////////////////
A = (double *)malloc(n * n * sizeof(double));
if (!A) {
printf("memory failed \n");
exit(1);
}
///////////////////// Matrix B //////////////////////////
B = (double *)malloc(n * n * sizeof(double));
if (!B) {
printf("memory failed \n");
exit(1);
}
///////////////////// Matrix C //////////////////////////
C = (double *)malloc(n * n * sizeof(double));
if (!C) {
printf("memory failed \n");
exit(1);
}
// initialize the matrices
for (i = 0; i < n * n; i++) {
A[i] = rand() % 15;
B[i] = rand() % 10;
C[i] = 0.;
}
clock_t t1 = clock();
working_thread = malloc(num_of_thrds * sizeof(pthread_t));
slice = malloc(num_of_thrds * sizeof(matrix_slice));
mutex = malloc(sizeof(pthread_mutex_t));
num_of_columns_per_slice = n / num_of_thrds;
for(i = 0; i < num_of_thrds; i++){
slice[i].b = B + i * num_of_columns_per_slice;
slice[i].c = C + i * num_of_columns_per_slice;
slice[i].mutex = mutex;
slice[i].num_of_columns = (i == num_of_thrds - 1) ? n-i * num_of_columns_per_slice : num_of_columns_per_slice;
pthread_create(&working_thread[i], NULL, matrix_slice_multiply, (void *)&slice[i]);
}
for(i = 0; i < num_of_thrds; i++)
pthread_join(working_thread[i], NULL);
clock_t t2=clock();
printf("elapsed time: %f\n", (double)(t2 - t1)/CLOCKS_PER_SEC);
printf("column sum norm is %f\n", matrix_norm);
//deallocate memory
free(A);
free(B);
free(C);
free(working_thread);
free(slice);
return 0;
}
我用各种输入运行程序数十次,结果发现使用的线程越多,花费的时间就越多。这是相当反直觉的。更多线程不应该有助于提高性能吗?
【问题讨论】:
-
嗯,您使用clock() 来测量时间,它将测量总CPU 时间,而不是挂钟时间。
-
你的矩阵有哪些维度?创建线程会导致一些开销;如果你的矩阵不够大,那么开销可能比多线程节省的成本要大。
-
作为一个建议:下次请缩进代码,这是不可读的
-
非常感谢,不。你的回答正是我想要的。我肯定会使用挂钟时间。
标签: c pthreads openmp matrix-multiplication