0
멀티 쓰레드 프로그램 파이 계산 번호를 씁니다. 그 숫자는 SIGINT 시그널을 보내지 않고 모든 플로우를 멈추고 응답을받을 때까지 고려됩니다. 그러나 불행히도 나는 버그를 이해할 수 없다. 그런 다음 신호를 보낼 때가끔 잘못된 결과를 받는다. 예를 들어 4 또는 3.17은 특정 숫자만큼 끝나기 쉽다면 신호를 보낼 때만 발생한다. 반복의 모든 것이 정상입니다. 도와주세요.파이 멀티 쓰레드 계산하기 pthread
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
union params {
unsigned long long idx;
double sum;
};
#define module (1299709L)
#define num_steps_per_check (1)
unsigned long long *CntIter = NULL;
int num_threads = 0;
int is_interrupted = 0;
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
void* partial_sum(void *ptr);
void handlesgint(int sig);
int main(int argc, char* argv[])
{
double pi = 0;
unsigned long long i;
int opt;
pthread_t* ids;
union params* params;
int ret_code = 0;
// parse command line
if (1 == argc) {
fprintf(stderr, "Usage: %s -n num_threads\n", argv[0]);
exit (EXIT_FAILURE);
}
while ((opt = getopt(argc, argv, "n:")) != -1)
{
switch (opt)
{
case 'n':
num_threads = atoi(optarg);
if (num_threads <= 0 /*|| num_threads >= _POSIX_THREAD_THREADS_MAX*/) {
fprintf(stderr, "quantity of threads invalid\n");
exit(EXIT_FAILURE);
}
break;
default:
fprintf(stderr, "Usage: %s -n num_threads\n", argv[0]);
exit(EXIT_FAILURE);
}
}
// setting handler
if (SIG_ERR == signal(SIGINT, handlesgint)) {
perror("fail signal");
exit(EXIT_FAILURE);
}
// init memory
params = (union params *)malloc(num_threads * sizeof(union params));
CntIter = (unsigned long long *)calloc(num_threads, sizeof(long long));
ids = (pthread_t *)malloc(num_threads * sizeof(pthread_t));
// operation distribution
for (i = 0; i < num_threads; ++i) {
params[i].idx = i;
ret_code = pthread_create(ids + i, NULL, partial_sum, (void*)(params + i));
if (0 != ret_code) {
perror("pthread create");
exit (EXIT_FAILURE);
}
}
// joining
for (i = 0; i < num_threads; ++i) {
union params* res;
ret_code = pthread_join(ids[i], (void **)&res);
if (0 != ret_code) {
perror("pthread join");
exit (EXIT_FAILURE);
}
pi += res->sum;
}
pi *= 4.0;
printf ("\npi = %.16f\n", pi);
// free resources
free(params);
free(ids);
free(CntIter);
return (EXIT_SUCCESS);
}
void* partial_sum(void *ptr) {
double sum = 0;
int idx = ((union params *)ptr)->idx;
unsigned long long i = 0;
unsigned long long index = 0;
int ret_code = 0;
int terminating = 0;
int sign = 0;
sigset_t set;
// Block SIGINT
sigemptyset(&set);
sigaddset(&set, SIGINT);
ret_code = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (0 != ret_code) {
perror("fail sigmask");
exit(EXIT_FAILURE);
}
i = 0;
while (0 == terminating) {
index = num_threads * i + idx;
sign = (0 == index % 2 ? 1 : -1);
sum += sign * (1.0/(2 * index + 1));
CntIter[idx] = (CntIter[idx] + 1) % module;
//if (i == 1000000L) { - !!!If to uncomment it and not to send a signal, result correct
// break;
//}
// check flag
if (0 == (i % num_steps_per_check)) {
pthread_rwlock_rdlock(&rwlock);
if (1 == is_interrupted) {
terminating = 1;
}
pthread_rwlock_unlock(&rwlock);
}
++i;
}
((union params *)ptr)->sum = sum;
return ptr;
}
void handlesgint(int sig) {
pthread_rwlock_wrlock(&rwlock);
is_interrupted = 1;
pthread_rwlock_unlock(&rwlock);
}
당신은 계산 일찍 중지하는 경우, 당신이 정확한 결과를 얻을 수없는 것을 말하는 것입니다. 기대하지 않습니까? 예 : 하나의 스레드 만 있으면 하나의 반복 후에 중단되고 4를 얻게됩니다. – ugoren
네, 맞습니다. 수정 된 코드 나는 다음의 게시물을 퍼뜨렸다. 고맙습니다. – Dima00782