使用 pthreads 进行练习,但我的代码中出现了一些意外行为
Exercising with pthreads but I am having some unexpected behaviours in my code
我想用 c 编写一个程序,它将使用 pthreads 对数组的平方数求和以实现代码的并行执行,但是在 linux 环境中执行代码时我得到分段错误(核心被愚弄) 消息。
奇怪的是,当我通过 DevC++ 在 windows 环境中 运行 完全相同的代码时,代码执行没有问题。
除此之外,似乎只有 1 个线程正在完成导致串行执行的工作。
我不知道我是否错了,但 pthread_self()
返回的是同一个 ID。我还是pthreads和一般编程的新手,我找不到问题所在,所以我需要你的帮助。
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <math.h>
void *calculation(int table[], int k);
pthread_mutex_t sum_mutex = PTHREAD_MUTEX_INITIALIZER;
int n, p, sum = 0;
int main()
{
int i, k=0, check, *table;
printf("Give the number of threads:\n");
scanf("%d",&p);
pthread_t threads[p];
printf("Give the number of elements of the table:");
do{
printf("The number of elements must be an integral multiple of the number of threads\n");
scanf("%d",&n);
check=n%p;
if(check!=0){
printf("Jesus how hard is it?\n");
printf("Try one more time\n");
printf("Give the number of elements of the table:\n");
}
}while(check!=0);
table = (int*) malloc(n * sizeof(int));
if(table == NULL){
printf("Error! Memory not allocated.\n");
exit(0);
}
printf("Give the elements of the table:\n");
for(i=0;i<n;i++){
scanf("%d",&table[i]);
}
for(i=0;i<p;i++){ //thread creation
pthread_create(&threads[i], NULL, calculation(table, k), NULL);
k++; //k is a variable used to seperate table, explained later
}
for(i=0;i<p;i++){
pthread_join(threads[i],NULL);
}
printf("Sum of vector= %d\n",sum);
free(table);
exit(0);
return 0;
}
void *calculation(int table[], int k){
int i;
int local_sum=0;
for(i=(n/p)*k;i<(n/p)*(k+1);i++) //this algorithm seperates the table into equivelant pieces and
{ //every pthread is calculating its given piece then stores that value in its local variable sum
if((n/p)>n){ //then it is updating the global variable
pthread_exit(NULL);
}
local_sum+=pow(table[i], 2);
printf("Thread's %lu calculation is %d\n", pthread_self(), local_sum);
}
pthread_mutex_lock(&sum_mutex); //mutex used here to protect the critical code
sum += local_sum;
pthread_mutex_unlock(&sum_mutex);
}
如果我没记错的话一个线程是运行一个不同的"copy"代码,因此每个线程的局部变量是不同的。在计算 local_sum 之后,它会更新出于明显原因而受到保护的全局总和。
正如我所说,在 windows 环境中,这段代码 运行 很流畅,但似乎是同一个 pthread 完成了所有工作。相反,应该将工作分成与存在的线程一样多的部分。
不要忘记在 linux 环境中核心根本没有运行导致错误的事实:分段错误(核心变笨)。
来自手册页,pthread_create
的声明
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
pthread_create的第三个参数是一个函数指针,它以void*
为参数。
在你的情况下你有两个参数 void *calculation(int table[], int k);
您向 pthread_create
传递参数的方式也是错误的,它应该只是函数名而不是其参数。(阅读更多关于回调函数的信息)。最后的NULL
应该是参数。在你的情况下你想传递 table
和 k
但它应该是一个指针。
pthread_create(&threads[i], NULL, calculation(table, k), NULL);
下面,我修改了代码,引入了一个新的struct thread_arg
,其中包含table
和k
,这个struct
会传给你的calculation
然后解包并正常使用。
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <math.h>
struct thread_arg {
int *table;
int k;
};
void *calculation(void *);
pthread_mutex_t sum_mutex = PTHREAD_MUTEX_INITIALIZER;
int n, p, sum = 0;
int main()
{
int i, k=0, check, *table;
printf("Give the number of threads:\n");
scanf("%d",&p);
pthread_t threads[p];
printf("Give the number of elements of the table:");
do{
printf("The number of elements must be an integral multiple of the number of threads\n");
scanf("%d",&n);
check=n%p;
if(check!=0){
printf("Jesus how hard is it?\n");
printf("Try one more time\n");
printf("Give the number of elements of the table:\n");
}
}while(check!=0);
table = (int*) malloc(n * sizeof(int));
if(table == NULL){
printf("Error! Memory not allocated.\n");
exit(0);
}
printf("Give the elements of the table:\n");
for(i=0;i<n;i++){
scanf("%d",&table[i]);
}
// edit: since I know the size allocated memory for th_args;
struct thread_arg th_args[p];
for(i=0;i<p;i++){ //thread creation
th_args[i].table = table;
th_args[i].k = k;
pthread_create(&threads[i], NULL, calculation, &th_args[i]);
k++; //k is a variable used to seperate table, explained later
}
for(i=0;i<p;i++){
pthread_join(threads[i],NULL);
}
printf("Sum of vector= %d\n",sum);
free(table);
exit(0);
return 0;
}
void *calculation(void *data){
int i;
int local_sum=0;
int *table;
int k;
struct thread_arg *th_args = data;
k = th_args->k;
table = th_args->table;
printf("shubham: thread_spawned\n");
for(i=(n/p)*k;i<(n/p)*(k+1);i++) //this algorithm seperates the table into equivelant pieces and
{ //every pthread is calculating its given piece then stores that value in its local variable sum
if((n/p)>n){ //then it is updating the global variable
pthread_exit(NULL);
}
local_sum+=pow(table[i], 2);
printf("Thread's %lu calculation is %d\n", pthread_self(), local_sum);
}
pthread_mutex_lock(&sum_mutex); //mutex used here to protect the critical code
sum += local_sum;
pthread_mutex_unlock(&sum_mutex);
// edit: function returs NULL;
return NULL;
}
Edit1:现在 calculation
returns NULL
,通过创建 p
th_args
处理了 k++
案例
我想用 c 编写一个程序,它将使用 pthreads 对数组的平方数求和以实现代码的并行执行,但是在 linux 环境中执行代码时我得到分段错误(核心被愚弄) 消息。
奇怪的是,当我通过 DevC++ 在 windows 环境中 运行 完全相同的代码时,代码执行没有问题。
除此之外,似乎只有 1 个线程正在完成导致串行执行的工作。
我不知道我是否错了,但 pthread_self()
返回的是同一个 ID。我还是pthreads和一般编程的新手,我找不到问题所在,所以我需要你的帮助。
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <math.h>
void *calculation(int table[], int k);
pthread_mutex_t sum_mutex = PTHREAD_MUTEX_INITIALIZER;
int n, p, sum = 0;
int main()
{
int i, k=0, check, *table;
printf("Give the number of threads:\n");
scanf("%d",&p);
pthread_t threads[p];
printf("Give the number of elements of the table:");
do{
printf("The number of elements must be an integral multiple of the number of threads\n");
scanf("%d",&n);
check=n%p;
if(check!=0){
printf("Jesus how hard is it?\n");
printf("Try one more time\n");
printf("Give the number of elements of the table:\n");
}
}while(check!=0);
table = (int*) malloc(n * sizeof(int));
if(table == NULL){
printf("Error! Memory not allocated.\n");
exit(0);
}
printf("Give the elements of the table:\n");
for(i=0;i<n;i++){
scanf("%d",&table[i]);
}
for(i=0;i<p;i++){ //thread creation
pthread_create(&threads[i], NULL, calculation(table, k), NULL);
k++; //k is a variable used to seperate table, explained later
}
for(i=0;i<p;i++){
pthread_join(threads[i],NULL);
}
printf("Sum of vector= %d\n",sum);
free(table);
exit(0);
return 0;
}
void *calculation(int table[], int k){
int i;
int local_sum=0;
for(i=(n/p)*k;i<(n/p)*(k+1);i++) //this algorithm seperates the table into equivelant pieces and
{ //every pthread is calculating its given piece then stores that value in its local variable sum
if((n/p)>n){ //then it is updating the global variable
pthread_exit(NULL);
}
local_sum+=pow(table[i], 2);
printf("Thread's %lu calculation is %d\n", pthread_self(), local_sum);
}
pthread_mutex_lock(&sum_mutex); //mutex used here to protect the critical code
sum += local_sum;
pthread_mutex_unlock(&sum_mutex);
}
如果我没记错的话一个线程是运行一个不同的"copy"代码,因此每个线程的局部变量是不同的。在计算 local_sum 之后,它会更新出于明显原因而受到保护的全局总和。
正如我所说,在 windows 环境中,这段代码 运行 很流畅,但似乎是同一个 pthread 完成了所有工作。相反,应该将工作分成与存在的线程一样多的部分。
不要忘记在 linux 环境中核心根本没有运行导致错误的事实:分段错误(核心变笨)。
来自手册页,pthread_create
的声明int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
pthread_create的第三个参数是一个函数指针,它以void*
为参数。
在你的情况下你有两个参数 void *calculation(int table[], int k);
您向 pthread_create
传递参数的方式也是错误的,它应该只是函数名而不是其参数。(阅读更多关于回调函数的信息)。最后的NULL
应该是参数。在你的情况下你想传递 table
和 k
但它应该是一个指针。
pthread_create(&threads[i], NULL, calculation(table, k), NULL);
下面,我修改了代码,引入了一个新的struct thread_arg
,其中包含table
和k
,这个struct
会传给你的calculation
然后解包并正常使用。
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <math.h>
struct thread_arg {
int *table;
int k;
};
void *calculation(void *);
pthread_mutex_t sum_mutex = PTHREAD_MUTEX_INITIALIZER;
int n, p, sum = 0;
int main()
{
int i, k=0, check, *table;
printf("Give the number of threads:\n");
scanf("%d",&p);
pthread_t threads[p];
printf("Give the number of elements of the table:");
do{
printf("The number of elements must be an integral multiple of the number of threads\n");
scanf("%d",&n);
check=n%p;
if(check!=0){
printf("Jesus how hard is it?\n");
printf("Try one more time\n");
printf("Give the number of elements of the table:\n");
}
}while(check!=0);
table = (int*) malloc(n * sizeof(int));
if(table == NULL){
printf("Error! Memory not allocated.\n");
exit(0);
}
printf("Give the elements of the table:\n");
for(i=0;i<n;i++){
scanf("%d",&table[i]);
}
// edit: since I know the size allocated memory for th_args;
struct thread_arg th_args[p];
for(i=0;i<p;i++){ //thread creation
th_args[i].table = table;
th_args[i].k = k;
pthread_create(&threads[i], NULL, calculation, &th_args[i]);
k++; //k is a variable used to seperate table, explained later
}
for(i=0;i<p;i++){
pthread_join(threads[i],NULL);
}
printf("Sum of vector= %d\n",sum);
free(table);
exit(0);
return 0;
}
void *calculation(void *data){
int i;
int local_sum=0;
int *table;
int k;
struct thread_arg *th_args = data;
k = th_args->k;
table = th_args->table;
printf("shubham: thread_spawned\n");
for(i=(n/p)*k;i<(n/p)*(k+1);i++) //this algorithm seperates the table into equivelant pieces and
{ //every pthread is calculating its given piece then stores that value in its local variable sum
if((n/p)>n){ //then it is updating the global variable
pthread_exit(NULL);
}
local_sum+=pow(table[i], 2);
printf("Thread's %lu calculation is %d\n", pthread_self(), local_sum);
}
pthread_mutex_lock(&sum_mutex); //mutex used here to protect the critical code
sum += local_sum;
pthread_mutex_unlock(&sum_mutex);
// edit: function returs NULL;
return NULL;
}
Edit1:现在 calculation
returns NULL
,通过创建 p
th_args
k++
案例