Pthreads矩阵乘法误差

我想在现有的串行矩阵乘法代码上使用pthreads。 我的目标是使用pthreads实现更好的执行时间,只是为了实现加速。 但那时我被困住了。 我的原始序列号,工作正常,我在大约15秒内完成1000×1000方阵乘法。 但是当我执行当前的pthreads程序时,我遇到了分段错误。 这是我的代码:

#include  #include  #include  #include  int SIZE, NTHREADS; int **A, **B, **C; void init() { int i, j; A = (int**)malloc(SIZE * sizeof(int *)); for(i = 0; i < SIZE; i++) A[i] = malloc(SIZE * sizeof(int)); B = (int**)malloc(SIZE * sizeof(int *)); for(i = 0; i < SIZE; i++) B[i] = malloc(SIZE * sizeof(int)); C = (int**)malloc(SIZE * sizeof(int *)); for(i = 0; i < SIZE; i++) C[i] = malloc(SIZE * sizeof(int)); srand(time(NULL)); for(i = 0; i < SIZE; i++) { for(j = 0; j < SIZE; j++) { A[i][j] = rand()%100; B[i][j] = rand()%100; } } } void mm(int tid) { int i, j, k; int start = tid * SIZE/NTHREADS; int end = (tid+1) * (SIZE/NTHREADS) - 1; for(i = start; i <= end; i++) { for(j = 0; j < SIZE; j++) { C[i][j] = 0; for(k = 0; k < SIZE; k++) { C[i][j] += A[i][k] * B[k][j]; } } } } void *worker(void *arg) { int tid = *((int *) arg); mm(tid); } int main(int argc, char* argv[]) { pthread_t* threads; int rc, i; if(argc != 3) { printf("Usage: %s  \n", argv[0]); exit(1); } SIZE = atoi(argv[1]); NTHREADS = atoi(argv[2]); init(); threads = (pthread_t*)malloc(NTHREADS * sizeof(pthread_t)); clock_t begin, end; double time_spent; begin = clock(); for(i = 0; i < NTHREADS; i++) { rc = pthread_create(&threads[i], NULL, worker, (void *)i); assert(rc == 0); } for(i = 0; i < NTHREADS; i++) { rc = pthread_join(threads[i], NULL); assert(rc == 0); } end = clock(); time_spent = (double)(end - begin) / CLOCKS_PER_SEC; printf("Elapsed time: %.2lf seconds.\n", time_spent); for(i = 0; i < SIZE; i++) free((void *)A[i]); free((void *)A); for(i = 0; i < SIZE; i++) free((void *)B[i]); free((void *)B); for(i = 0; i < SIZE; i++) free((void *)C[i]); free((void *)C); free(threads); return 0; } 

如果有人可以帮助我让我的pthreads程序运行,并实现一些加速,我会很高兴。

使用当前代码,您应该使用检索索引

 int tid = (int)arg; 

(您的代码有效地将循环计数器视为一个地址,然后在0或大约0处解除引用地址。这些地址可能无法被您的进程读取和/或将无法正确对齐,因此seg错误)

上面的更改可能会让事情适合你,但请注意,将int作为void*传递并不完全正确。 它依赖于sizeof(int) <= sizeof(void*) ,这可能但不保证是真的。 如果您关心这一点,您可以为传递给每个线程的数据分配内存,也可以传递i的地址并包含同步,以确保在每次pthread_create调用之后等待,直到线程已经被调度并读取了它的arg。