Ubuntu下使用pthreads实现矩阵向量乘法触发Segmentation fault问题
Ubuntu下多线程矩阵-向量乘法段错误问题修复
问题根源分析
- Windows专属代码冗余:代码开头的
#pragma comment(lib, "pthreadVC2.lib")是Windows平台链接pthread库的指令,Ubuntu下GCC完全不识别;#define _CRT_SECURE_NO_WARNINGS 1是VS编译器的安全警告禁用宏,Linux下无效,这两行直接删掉即可。 - 命令行参数未检查:main函数直接读取
argv[1]设置线程数,如果运行时没传参数,argv[1]是空指针,调用atoi会直接触发段错误,表现为程序还没输出任何内容就崩溃,看起来像没进入main函数。 - 函数参数类型不匹配:
Print_vector函数的第三个参数定义为double m,但实际传入的是int类型的矩阵行数,虽然不会直接崩溃,但属于类型错误,容易引发逻辑问题。 - 线程任务划分不完整:当矩阵行数m不能被线程数整除时,现有代码会遗漏最后几行的计算,需要调整线程的行范围逻辑。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <pthread.h> /* Global variables */ int thread_count = 8; int m, n; double* A = NULL; double* x = NULL; double* y = NULL; /* Serial functions */ void Usage(char* prog_name); void Read_matrix(char* prompt, double A[], int m, int n); void Read_vector(char* prompt, double x[], int n); void Print_matrix(char* title, double A[], int m, int n); void Print_vector(char* title, double y[], int m); /* Parallel function */ void* Pth_mat_vect(void* rank); /*------------------------------------------------------------------*/ int main(int argc, char* argv[]) { long thread; pthread_t* thread_handles; // 检查命令行参数 if (argc != 2) { fprintf(stderr, "用法: %s <线程数>\n", argv[0]); exit(EXIT_FAILURE); } thread_count = atoi(argv[1]); thread_handles = malloc(thread_count * sizeof(pthread_t)); if (thread_handles == NULL) { fprintf(stderr, "malloc线程句柄失败\n"); exit(EXIT_FAILURE); } printf("Enter m and n\n"); scanf("%d%d", &m, &n); A = malloc(m * n * sizeof(double)); x = malloc(n * sizeof(double)); y = malloc(m * sizeof(double)); // 检查内存分配是否成功 if (A == NULL || x == NULL || y == NULL) { fprintf(stderr, "malloc内存失败\n"); exit(EXIT_FAILURE); } Read_matrix("Enter the matrix", A, m, n); Print_matrix("We read", A, m, n); Read_vector("Enter the vector", x, n); Print_vector("We read", x, n); for (thread = 0; thread < thread_count; thread++) pthread_create(&thread_handles[thread], NULL, Pth_mat_vect, (void*)thread); for (thread = 0; thread < thread_count; thread++) pthread_join(thread_handles[thread], NULL); Print_vector("The product is", y, m); free(A); free(x); free(y); free(thread_handles); // 释放线程句柄内存 return 0; } /* main */ /*------------------------------------------------------------------ * Function: Read_matrix * Purpose: Read in the matrix * In args: prompt, m, n * Out arg: A */ void Read_matrix(char* prompt, double A[], int m, int n) { int i, j; printf("%s\n", prompt); for (i = 0; i < m; i++) for (j = 0; j < n; j++) scanf("%lf", &A[i * n + j]); } /* Read_matrix */ /*------------------------------------------------------------------ * Function: Read_vector * Purpose: Read in the vector x * In arg: prompt, n * Out arg: x */ void Read_vector(char* prompt, double x[], int n) { int i; printf("%s\n", prompt); for (i = 0; i < n; i++) scanf("%lf", &x[i]); } /* Read_vector */ /*------------------------------------------------------------------ * Function: Pth_mat_vect * Purpose: Multiply an mxn matrix by an nx1 column vector * In arg: rank * Global in vars: A, x, m, n, thread_count * Global out var: y */ void* Pth_mat_vect(void* rank) { long my_rank = (long)rank; int i, j; int local_m = m / thread_count; int my_first_row = my_rank * local_m; // 处理不能整除的情况,最后一个线程负责剩余所有行 int my_last_row = (my_rank == thread_count - 1) ? m - 1 : (my_rank + 1) * local_m - 1; for (i = my_first_row; i <= my_last_row; i++) { y[i] = 0.0; for (j = 0; j < n; j++) y[i] += A[i * n + j] * x[j]; } return NULL; } /* Pth_mat_vect */ /*------------------------------------------------------------------ * Function: Print_matrix * Purpose: Print the matrix * In args: title, A, m, n */ void Print_matrix(char* title, double A[], int m, int n) { int i, j; printf("%s\n", title); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) printf("%4.1f ", A[i * n + j]); printf("\n"); } } /* Print_matrix */ /*------------------------------------------------------------------ * Function: Print_vector * Purpose: Print a vector * In args: title, y, m */ void Print_vector(char* title, double y[], int m) { int i; printf("%s\n", title); for (i = 0; i < m; i++) printf("%4.1f ", y[i]); printf("\n"); } /* Print_vector */
编译与运行步骤
- 保存修复后的代码为
mat_vec.c - 使用GCC编译,必须链接pthread库:
gcc -o mat_vec mat_vec.c -lpthread - 运行程序,必须传入线程数参数(例如4线程):
./mat_vec 4 - 按照提示输入矩阵行数m、列数n,依次输入矩阵元素和向量元素即可。
内容的提问来源于stack exchange,提问作者Shuhao Chu
相关产品推荐
相关产品推荐

