Em sử dụng giải thuật Monte Carlo để tính số pi.
Em làm theo 2 cách : đơn luồng và đa luồng. (Em để code ở cuối bài post)
Code của em chạy đúng và trả về số Pi xấp xỉ 3,14
.
Nhưng có một vấn đề là đoạn code đa luồng chạy rất chậm
Cụ thể là với 100 000 000(1 trăm triệu) lần lặp thì
- Đơn luồng là 3s
- Đa luồng là 21s
Mọi người cho em hỏi là vì sao lại như vậy ạ ???
Hiện thực theo C (Đơn luồng)
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
//#define PI 3.1415926535897
void calPI();
uint64_t count = 0, range; // Shared data
time_t start = 0, end = 0; // Time variables
int main(int argc, char const *argv[])
{
assert(argc == 2 && "TheNumberOfArgumentsIsWrong");
assert(atoll(argv[1]) > 0 && "Argument must be >= 0");
// Set test range
range = atoll(argv[1]);
//*---------------------------------------*//
time(&start); // Start counting time
calPI();
time(&end); // End counting time
//*---------------------------------------*//
double pi = 4.0*(double)count/(double)range;
printf("%.1lf\n", pi); // Print PI Number
double time = difftime(end, start);
printf("%.1lf(s)\n", time); // Print time to excute
return EXIT_SUCCESS;
}
void calPI() {
// Initialize the pseudo number
srand(time(NULL));
// Monte Carlo technique
for(uint64_t i = 0; i < range; ++i) {
// Create point
double x = (double)rand()/(double)RAND_MAX;
double y = (double)rand()/(double)RAND_MAX;
// Calculator radius
double r = sqrt(x*x + y*y);
// Is it in a circle
if(r <= 1) count = count + 1;
}
}
/******************************************************************************
* * FILE: pi_serial.c
* * DESCRIPTION:
* * Calculates the value of pi using a parallel implementation using pthreads
* *
* * HOW TO COMPILE:
* * gcc -lm pi_serial.c
* * HOW TO RUN:
* * ./a.out 100000000
* *
* * AUTHOR: Đỗ Đăng Khôi
* ******************************************************************************/
Hiện thực theo C (Đa luồng)
Em sử dụng thư viện pthread.h
của C trong Linux
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#include <assert.h>
#define NUM_THREAD 10
//#define PI 3.1415926535897
void* calPI(void *param);
pthread_t thdIDs[NUM_THREAD] = {}; // Thread IDs
uint64_t counts[NUM_THREAD] = {}; // Points in circle
uint64_t count = 0, range; // Shared data
time_t start = 0, end = 0; // Time variables
int main(int argc, char const *argv[])
{
assert(argc == 2 && "TheNumberOfArgumentsIsWrong");
assert(atoll(argv[1]) > 0 && "Argument must be >= 0");
// Set test range
range = atoll(argv[1])/NUM_THREAD;
//*---------------------------------------*//
time(&start); // Start counting time
for(int8_t i = 0; i < NUM_THREAD; ++i)
pthread_create(&thdIDs[i], NULL, calPI, &counts[i]);
for(int8_t i = 0; i < NUM_THREAD; ++i) {
pthread_join(thdIDs[i], NULL);
count += counts[i]; // The number of points in the circle
}
time(&end); // End counting time
//*---------------------------------------*//
double pi = 4.0*(double)count/(double)range/(double)NUM_THREAD;
printf("%.1lf\n", pi); // Print PI Number
double time = difftime(end, start);
printf("%.1lf(s)\n", time); // Print time to excute
pthread_exit(EXIT_SUCCESS);
}
void* calPI(void *arg) {
// Initialize the pseudo number
// srand(time(NULL));
// Monte Carlo technique
uint64_t* pcount = (uint64_t*)arg;
for(uint64_t i = 0; i < range; ++i) {
// Create point
double x = (double)rand()/(double)RAND_MAX;
double y = (double)rand()/(double)RAND_MAX;
// Calculator radius
double r = sqrt(x*x + y*y);
// Is it in a circle
if(r <= 1) *pcount = *pcount + 1;
}
// End thread
pthread_exit(EXIT_SUCCESS);
}
/******************************************************************************
* * FILE: pi_multi_thread.c
* * DESCRIPTION:
* * Calculates the value of pi using a parallel implementation using pthreads
* *
* * HOW TO COMPILE:
* * gcc -lm -pthread pi_multi_thread.c
* * HOW TO RUN:
* * ./a.out 100000000
* *
* * AUTHOR: Đỗ Đăng Khôi
* ******************************************************************************/