在for循环中一次又一次地创建和连接线程(C)
我写了一个程序,在C语言中执行高斯消去,并返回矩阵的L2范数。该程序的调用类似于在for循环中一次又一次地创建和连接线程(C),c,loops,for-loop,pthreads,C,Loops,For Loop,Pthreads,我写了一个程序,在C语言中执行高斯消去,并返回矩阵的L2范数。该程序的调用类似于/exec n k,其中n是nxn矩阵的大小,k是将用于执行该程序的线程数(最多4个)。我像./gauss304那样运行程序,它会出错 在使用GDB之后,我发现有比预期多得多的线程退出,我认为因为我的线程是在for循环中生成的,它们被一次又一次地连接和创建,这导致了seg故障。有人能给我指一下正确的方向吗 #include <stdlib.h> #include <stdio.h> #incl
/exec n k
,其中n是nxn矩阵的大小,k是将用于执行该程序的线程数(最多4个)。我像./gauss304那样运行程序,它会出错
在使用GDB之后,我发现有比预期多得多的线程退出,我认为因为我的线程是在for循环中生成的,它们被一次又一次地连接和创建,这导致了seg故障。有人能给我指一下正确的方向吗
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <omp.h>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>
//globals
double **a, *vect, *bvect, scalar, ratio, sum, delta, *temp;
int i,j,k,ptr, z;
int y,z;
int bvectcount = 0;
int threadcount;
pthread_t workerThreads[4];
typedef struct threader {
int counter;
int matrixl;
} threader;
struct timeval start, end;
void *retval;
int checkargs(int argc, char* argv[]);
// a is matrix, b is vector, x is the solution vector, and n is the size
double L2(double **a, double *bvect, double *vect, int matrixSize) {
double sum;
double res[matrixSize];
int i, j;
for (i=0; i < matrixSize; i++) {
sum = (double) 0;
for (j=0; j < matrixSize; j++) {
sum += a[i][j] * vect[j];
}
res[i] = sum;
}
for (i=0; i < matrixSize; i++) {
res[i] -= vect[i];
}
double squaresum = (double) 0;
for (i=0; i < matrixSize; i++) {
squaresum += res[i] * res[i];
}
return sqrt(squaresum);
}
int checkargs(int argc, char* argv[]){
if(argc != 3){
fprintf(stderr, "Error: Usage is size threadNum\n" );
exit(1);
}
}
void *parallelstuff(void *args){
threader temp = *((threader *)args);
int i, matrixSize;
i = temp.counter;
matrixSize = temp.matrixl;
double temp2;
for(j = i + 1; j<matrixSize; j++){
temp2 = a[j][i]/a[i][i];
for(z = 0; z<matrixSize + 1; z++){
a[j][z] = a[j][z] - temp2 * a[i][z];
}
}
}
int main(int argc, char* argv[]){
//check for args
checkargs(argc, argv);
int matrixSize = atoi(argv[1]);
int threadNum = atoi(argv[2]);
//memory allocation
a = (double**)malloc(matrixSize*sizeof(double*));
for(i = 0; i < matrixSize ; i++)
a[i] = (double*)malloc(matrixSize*sizeof(double) * matrixSize);
vect = (double*)malloc(matrixSize*sizeof(double));
bvect = (double*)malloc(matrixSize*sizeof(double));
temp = (double*)malloc(matrixSize*sizeof(double));
for(i = 0; i < matrixSize; ++i){
for(j = 0; j < matrixSize + 1; ++j){
a[i][j] = drand48();
}
}
j = 0;
j += matrixSize;
for(i = 0; i < matrixSize; ++i){
bvect[i] = a[i][j];
}
//generation of scalar matrix (diagonal vector)
gettimeofday(&start, NULL);
for(i=0; i<matrixSize; i++){
scalar = a[i][i];
//initialization of p to travel throughout matrix
ptr = i;
//find largest number in column and row number of it
for(k = i+1; k < matrixSize; k++){
if(fabs(scalar) < fabs(a[k][i])){
//k is row of scalar, while
scalar = a[k][i];
ptr = k;
}
}
//swaping the elements of diagonal row and row containing largest no
for(j = 0; j <= matrixSize; j++)
{
temp[0] = a[i][j];
a[i][j]= a[ptr][j];
a[ptr][j] = temp[0];
}
ratio = a[i][i];
for(k = 0; k < matrixSize + 1; k++){
a[i][k] = a[i][k] / ratio;
}
threader stuff;
stuff.counter = i;
stuff.matrixl = matrixSize;
//MAKE EACH THREAD DO SOMETHING DIFF
//
// parallelstuff(int i, int matrixSize, double **a){
for(threadcount = 0; threadcount < threadNum; threadcount++){
if(pthread_create (&workerThreads[threadcount], NULL, parallelstuff, (void *) &stuff ) != 0){
fprintf(stderr, "Error: consumer create problem\n");
exit(1);
}
}
while(threadcount != 0){
if(pthread_join (workerThreads[threadcount-1], &retval ) != 0){
fprintf(stderr, "Error: consumer create problem\n");
exit(1);
}
threadcount--;
}
//create matrix of n size
//backward substitution method
for(i=matrixSize-1; i >=0; i--){
for(k = i; k > 0; k--){
a[k-1][matrixSize] -= a[k-1][i] * a[i][matrixSize];
a[k-1][i] -= a[k-1][i] * a[i][i];
}
}
for(i = 0; i < matrixSize; ++i){
vect[i] = a[i][matrixSize];
}
double l2Norm;
l2Norm = L2(a, bvect, vect, matrixSize);
printf("THIS IS L2 NORM: %f\n", l2Norm);
gettimeofday(&end, NULL);
delta = ((end.tv_sec - start.tv_sec) * 1000000u +
end.tv_usec - start.tv_usec) / 1.e6;
printf("end time: %f\n", delta);
}
}
编辑:我在GDB中发现了一些有趣的东西,它告诉了我们很多关于这个问题的信息。这将永远循环,然后最终分段故障。有人能帮我理解这是什么吗
这一行
for(j = 0; j < matrixSize + 1; ++j){
a[i][j] = drand48();
}
(j=0;j{
a[i][j]=drand48();
}
错误,并导致在矩阵的每行末尾进行越界访问
您可以查看
valgrind
或类似的工具,帮助您检测此类越界访问。以下代码包含有关更改的注释
Note: for clarity and maintainability, only one variable per line
Note: for clarity, all braces are included
Note: added brace at end of main() function that should be elsewhere in the function
Note: there are still two compile problems, as noted in the code:
1) function drand48() not defined
2) parameter bvect in function l2 not used.
Please fix all the remaining problems in the code and re-post
#include <stdlib.h>
#include <stdio.h>
#include <math.h> // sqrt()
#include <omp.h>
#include <time.h> // time() gettimeofday()
#include <sys/time.h>
#include <pthread.h>
#include <string.h> // memcpy()
struct threader
{
int counter;
int matrixl;
};
//globals
double **a;
double *vect;
double *bvect;
double scalar;
double ratio;
double sum;
double delta;
double *temp;
int i;
int j;
int k;
int ptr;
int z;
int y;
//int z; <-- second declaration of same variable
int bvectcount = 0; // unused variable
int threadcount;
pthread_t workerThreads[4];
struct timeval start; // beginn execution time
struct timeval end; // end execution time
void *retval;
// prototypes
// a is matrix, b is vector, x is the solution vector, and n is the size
double L2(double **a, double *bvect, double *vect, int matrixSize);
// thread function
void *parallelstuff(void *args);
// check command line argumen counts
int checkargs(int argc, char* argv[]);
int main(int argc, char* argv[])
{
//check for args
checkargs(argc, argv);
int matrixSize = atoi(argv[1]);
if( 0 >= matrixSize )
{
// handle error; exit(1);
}
int threadNum = atoi(argv[2]);
if( (0 >= threadNum) || (4 < threadNum) )
{
// handle error; exit(1);
}
//memory allocation
if( NULL == (a = malloc(matrixSize*sizeof(double*)) ) )
{
// perror(); call cleanup; exit(1);
}
for(i = 0; i < matrixSize ; i++)
{
if( NULL == (a[i] = malloc(matrixSize*sizeof(double) * matrixSize) ) )
{
//perror(); call cleanup; exit(1);
}
}
if( NULL == (vect = malloc(matrixSize*sizeof(double)) ) )
{
// perror(); call cleanup; exit(1);
}
if( NULL == (bvect = malloc(matrixSize*sizeof(double)) ) )
{
// perror(); call cleanup; exit(1);
}
if( NULL == (temp = malloc(matrixSize*sizeof(double)) ) )
{
// perror(); call cleanup; exit(1);
}
for(i = 0; i < matrixSize; ++i)
{
for(j = 0; j < matrixSize + 1; ++j)
{
a[i][j] = drand48(); // where is this function defined?
}
}
j = matrixSize;
for(i = 0; i < matrixSize; ++i)
{
bvect[i] = a[i][j];
}
//generation of scalar matrix (diagonal vector)
gettimeofday(&start, NULL); // time how long this takes to execute
for(i=0; i<matrixSize; i++)
{
scalar = a[i][i];
//initialization of p to travel throughout matrix
ptr = i;
//find largest number in column and row number of it
for(k = i+1; k < matrixSize; k++)
{
if(fabs(scalar) < fabs(a[k][i]))
{
//k is row of scalar, while
scalar = a[k][i];
ptr = k;
}
}
//swaping the elements of diagonal row and row containing largest no
for(j = 0; j <= matrixSize; j++)
{
temp[0] = a[i][j];
a[i][j]= a[ptr][j];
a[ptr][j] = temp[0];
}
ratio = a[i][i];
for(k = 0; k < matrixSize + 1; k++)
{
a[i][k] = a[i][k] / ratio;
}
struct threader stuff;
stuff.counter = i;
stuff.matrixl = matrixSize;
// parallelstuff(int i, int matrixSize, double **a){
for(threadcount = 0; threadcount < threadNum; threadcount++)
{
if( pthread_create( &workerThreads[threadcount], NULL, parallelstuff, (void *) &stuff ) )
{
fprintf(stderr, "Error: consumer create problem\n");
exit(1);
}
}
while(threadcount != 0)
{
if(pthread_join (workerThreads[threadcount-1], &retval ) != 0)
{
fprintf(stderr, "Error: consumer create problem\n");
exit(1);
}
threadcount--;
}
//create matrix of n size
//backward substitution method
for(i=matrixSize-1; i >=0; i--)
{
for(k = i; k > 0; k--)
{
a[k-1][matrixSize] -= a[k-1][i] * a[i][matrixSize];
a[k-1][i] -= a[k-1][i] * a[i][i];
}
}
for(i = 0; i < matrixSize; ++i)
{
vect[i] = a[i][matrixSize];
}
double l2Norm;
l2Norm = L2(a, bvect, vect, matrixSize);
printf("THIS IS L2 NORM: %f\n", l2Norm);
gettimeofday(&end, NULL);
delta =
((end.tv_sec - start.tv_sec) * 1000000u + end.tv_usec - start.tv_usec) / 1.e6;
printf("end time: %f\n", delta);
return(0);
} // supply missing closing brace, just for testing, where should this actually be placed?
} // end function: main
double L2(double **a, double *bvect, double *vect, int matrixSize) // unused param: bvect
{
double sum;
double res[matrixSize];
int i;
int j;
for (i=0; i < matrixSize; i++)
{
sum = 0.0;
for (j=0; j < matrixSize; j++)
{
sum += a[i][j] * vect[j];
}
res[i] = sum;
}
for (i=0; i < matrixSize; i++)
{
res[i] -= vect[i];
}
double squaresum = 0.0;
for (i=0; i < matrixSize; i++)
{
squaresum += res[i] * res[i];
}
return sqrt(squaresum);
} // end function: L2
// this function changes global array 'a[]'
// to avoid race conditions, a mutex should be used to lock the resource (a[])
// while it is being modified
void *parallelstuff(void *args)
{
struct threader temp; // this shadows global 'temp' variable
memcpy ( &temp, (struct threader *)args, sizeof(struct threader) );
int j;
int z;
int i = temp.counter;
int matrixSize = temp.matrixl;
double temp2 = 0.0;
for(j = i + 1; j<matrixSize; j++)
{
temp2 = a[j][i] / a[i][i];
for(z = 0; z<matrixSize + 1; z++) // this will access memory beyond the bounds of 2d matrix a[]
{
a[j][z] = a[j][z] - temp2 * a[i][z];
}
}
pthread_exit( NULL );
} // end function: parallelstuff
int checkargs(int argc, char* argv[])
{
if(argc != 3)
{
fprintf(stderr, "Error: Usage: %s size threadNum\n", argv[0] );
exit(1);
}
return( 0 );
} // end function: checkargs
注意:为了清晰和可维护性,每行只有一个变量
注:为清晰起见,包括所有支架
注意:在main()函数末尾添加了大括号,该大括号应位于函数的其他位置
注意:如代码中所述,仍然存在两个编译问题:
1) 未定义函数drand48()
2) 函数l2中的参数bvect未使用。
请修复代码中的所有剩余问题并重新发布
#包括
#包括
#include//sqrt()
#包括
#包括//time()gettimeofday()
#包括
#包括
#include//memcpy()
结构螺纹机
{
整数计数器;
int矩阵;
};
//全球的
双**a;
双*向量;
双*bvect;
双标量;
双倍比率;
双和;
双三角洲;
双*温度;
int i;
int j;
int k;
int-ptr;
intz;
int-y;
//int z;=矩阵大小)
{
//处理错误;退出(1);
}
int threadNum=atoi(argv[2]);
如果((0>=threadNum)| |(4 对于(j=i+1;j2风格?我有一个checkargs的原型,以前我把main放在它上面,但是我把checkargs移到main上面,只是忘了把原型去掉。oops,我错过了;
首先,去掉程序中的所有类型转换。它们完全没有用,可能只是隐藏bug。然后不要把指针数组用作假矩阵。C有更容易处理的2D矩阵构建。类似于double(*A)[n]=malloc(sizeof(double[n][n]))
这项工作很容易完成。你的问题很可能只是你复杂的分配方案。另外,请正确缩进你的代码,这是一个阅读困难的问题。我已经缩进了不合适的行!这实际上是高斯消去法的一个增广矩阵,这是有意的,我担心是有意的还是无意的,你不分配他为它留出了空间。我已经修复了它。但是,我在OpenMP版本的程序中使用了几乎相同的代码,并且它运行得完美无缺。我知道我的代码是wro
Note: for clarity and maintainability, only one variable per line
Note: for clarity, all braces are included
Note: added brace at end of main() function that should be elsewhere in the function
Note: there are still two compile problems, as noted in the code:
1) function drand48() not defined
2) parameter bvect in function l2 not used.
Please fix all the remaining problems in the code and re-post
#include <stdlib.h>
#include <stdio.h>
#include <math.h> // sqrt()
#include <omp.h>
#include <time.h> // time() gettimeofday()
#include <sys/time.h>
#include <pthread.h>
#include <string.h> // memcpy()
struct threader
{
int counter;
int matrixl;
};
//globals
double **a;
double *vect;
double *bvect;
double scalar;
double ratio;
double sum;
double delta;
double *temp;
int i;
int j;
int k;
int ptr;
int z;
int y;
//int z; <-- second declaration of same variable
int bvectcount = 0; // unused variable
int threadcount;
pthread_t workerThreads[4];
struct timeval start; // beginn execution time
struct timeval end; // end execution time
void *retval;
// prototypes
// a is matrix, b is vector, x is the solution vector, and n is the size
double L2(double **a, double *bvect, double *vect, int matrixSize);
// thread function
void *parallelstuff(void *args);
// check command line argumen counts
int checkargs(int argc, char* argv[]);
int main(int argc, char* argv[])
{
//check for args
checkargs(argc, argv);
int matrixSize = atoi(argv[1]);
if( 0 >= matrixSize )
{
// handle error; exit(1);
}
int threadNum = atoi(argv[2]);
if( (0 >= threadNum) || (4 < threadNum) )
{
// handle error; exit(1);
}
//memory allocation
if( NULL == (a = malloc(matrixSize*sizeof(double*)) ) )
{
// perror(); call cleanup; exit(1);
}
for(i = 0; i < matrixSize ; i++)
{
if( NULL == (a[i] = malloc(matrixSize*sizeof(double) * matrixSize) ) )
{
//perror(); call cleanup; exit(1);
}
}
if( NULL == (vect = malloc(matrixSize*sizeof(double)) ) )
{
// perror(); call cleanup; exit(1);
}
if( NULL == (bvect = malloc(matrixSize*sizeof(double)) ) )
{
// perror(); call cleanup; exit(1);
}
if( NULL == (temp = malloc(matrixSize*sizeof(double)) ) )
{
// perror(); call cleanup; exit(1);
}
for(i = 0; i < matrixSize; ++i)
{
for(j = 0; j < matrixSize + 1; ++j)
{
a[i][j] = drand48(); // where is this function defined?
}
}
j = matrixSize;
for(i = 0; i < matrixSize; ++i)
{
bvect[i] = a[i][j];
}
//generation of scalar matrix (diagonal vector)
gettimeofday(&start, NULL); // time how long this takes to execute
for(i=0; i<matrixSize; i++)
{
scalar = a[i][i];
//initialization of p to travel throughout matrix
ptr = i;
//find largest number in column and row number of it
for(k = i+1; k < matrixSize; k++)
{
if(fabs(scalar) < fabs(a[k][i]))
{
//k is row of scalar, while
scalar = a[k][i];
ptr = k;
}
}
//swaping the elements of diagonal row and row containing largest no
for(j = 0; j <= matrixSize; j++)
{
temp[0] = a[i][j];
a[i][j]= a[ptr][j];
a[ptr][j] = temp[0];
}
ratio = a[i][i];
for(k = 0; k < matrixSize + 1; k++)
{
a[i][k] = a[i][k] / ratio;
}
struct threader stuff;
stuff.counter = i;
stuff.matrixl = matrixSize;
// parallelstuff(int i, int matrixSize, double **a){
for(threadcount = 0; threadcount < threadNum; threadcount++)
{
if( pthread_create( &workerThreads[threadcount], NULL, parallelstuff, (void *) &stuff ) )
{
fprintf(stderr, "Error: consumer create problem\n");
exit(1);
}
}
while(threadcount != 0)
{
if(pthread_join (workerThreads[threadcount-1], &retval ) != 0)
{
fprintf(stderr, "Error: consumer create problem\n");
exit(1);
}
threadcount--;
}
//create matrix of n size
//backward substitution method
for(i=matrixSize-1; i >=0; i--)
{
for(k = i; k > 0; k--)
{
a[k-1][matrixSize] -= a[k-1][i] * a[i][matrixSize];
a[k-1][i] -= a[k-1][i] * a[i][i];
}
}
for(i = 0; i < matrixSize; ++i)
{
vect[i] = a[i][matrixSize];
}
double l2Norm;
l2Norm = L2(a, bvect, vect, matrixSize);
printf("THIS IS L2 NORM: %f\n", l2Norm);
gettimeofday(&end, NULL);
delta =
((end.tv_sec - start.tv_sec) * 1000000u + end.tv_usec - start.tv_usec) / 1.e6;
printf("end time: %f\n", delta);
return(0);
} // supply missing closing brace, just for testing, where should this actually be placed?
} // end function: main
double L2(double **a, double *bvect, double *vect, int matrixSize) // unused param: bvect
{
double sum;
double res[matrixSize];
int i;
int j;
for (i=0; i < matrixSize; i++)
{
sum = 0.0;
for (j=0; j < matrixSize; j++)
{
sum += a[i][j] * vect[j];
}
res[i] = sum;
}
for (i=0; i < matrixSize; i++)
{
res[i] -= vect[i];
}
double squaresum = 0.0;
for (i=0; i < matrixSize; i++)
{
squaresum += res[i] * res[i];
}
return sqrt(squaresum);
} // end function: L2
// this function changes global array 'a[]'
// to avoid race conditions, a mutex should be used to lock the resource (a[])
// while it is being modified
void *parallelstuff(void *args)
{
struct threader temp; // this shadows global 'temp' variable
memcpy ( &temp, (struct threader *)args, sizeof(struct threader) );
int j;
int z;
int i = temp.counter;
int matrixSize = temp.matrixl;
double temp2 = 0.0;
for(j = i + 1; j<matrixSize; j++)
{
temp2 = a[j][i] / a[i][i];
for(z = 0; z<matrixSize + 1; z++) // this will access memory beyond the bounds of 2d matrix a[]
{
a[j][z] = a[j][z] - temp2 * a[i][z];
}
}
pthread_exit( NULL );
} // end function: parallelstuff
int checkargs(int argc, char* argv[])
{
if(argc != 3)
{
fprintf(stderr, "Error: Usage: %s size threadNum\n", argv[0] );
exit(1);
}
return( 0 );
} // end function: checkargs