使用 pthreads 来加速从 0 到 N 计算质数的处理。我使用它们是否正确?
Using pthreads to speed up the processing of counting prime numbers from 0 to N. Am I using them correctly?
我正在编写代码来计算从 0 到 N 的质数,利用 8 个 pthreads 来加速这个过程。我已经在线研究了 C 中的多线程,但我仍然不确定在这种情况下我是否正确使用了它们。他们真的在加快我程序的执行时间吗?如果我没记错的话,pthread是同时执行他们的函数的吧?
#include <pthread.h>
#include <stdio.h>
#include <math.h>
#define NUM_COUNT 800
#define NUM_THREADS 8
int counter = 0; //counter to count primes
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//function to find primes
int is_prime(int n) {
if (n < 2)return 0;
if (n == 2)return 1;
if (n % 2 == 0)return 0;
for (int i=3; i < n; i += 2) {
if (n % i == 0) return 0;
}
return 1;
}
void *PrintPrimes(void *threadid) {
int thread_start, thread_end;
int thread_id = (int)threadid; //store thread id in thread_id
thread_start = thread_id*(NUM_COUNT/NUM_THREADS); //determine where individual thread begins searching for primes
thread_end = thread_start+(NUM_COUNT/NUM_THREADS); //determine where thread ends searching for primes
for(int n = thread_start; n < thread_end; n++) {
if (is_prime(n)) {
pthread_mutex_lock(&mutex);
counter++;
printf("the number of primes is currently %d\n", counter);
pthread_mutex_unlock(&mutex);
}
}
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
for(int i = 0; i < NUM_THREADS; i++){
pthread_create(&threads[i], NULL, PrintPrimes, (void *)i);
}
pthread_exit(NULL);
}
我发现代码有一些问题:
您永远不会在线程上调用 pthread_join()
,这意味着您的程序将在生成线程后立即退出,而不是等待它们完成——这可能不是您想要的。您应该在 main()
函数的底部添加第二个像这样的 for 循环:
for(int i = 0; i < NUM_THREADS; i++) {
pthread_join(&threads[i], NULL);
}
main()
中对pthread_exit()
的调用是不必要的,可以去掉。 (它意味着从生成的 pthread 中调用以导致线程退出,没有必要从主线程调用它)
从线程的计算循环中调用 printf()
会大大减慢计算速度(以至于您根本不再测量实际计算的性能) ,而您实际上只是在测量 printf()
和 stdout 子系统执行的速度)
每次找到一个新的质数时都必须用互斥锁来保护 shared/global counter
效率不是很高;最好为每个线程声明一个 local/non-shared 计数器变量,并递增它。然后在线程执行结束时,您可以将线程的本地计数器添加到 shared/global 计数器一次,从而避免更多地支付 lock()/unlock() 序列带来的同步惩罚每个线程不止一次。
我正在编写代码来计算从 0 到 N 的质数,利用 8 个 pthreads 来加速这个过程。我已经在线研究了 C 中的多线程,但我仍然不确定在这种情况下我是否正确使用了它们。他们真的在加快我程序的执行时间吗?如果我没记错的话,pthread是同时执行他们的函数的吧?
#include <pthread.h>
#include <stdio.h>
#include <math.h>
#define NUM_COUNT 800
#define NUM_THREADS 8
int counter = 0; //counter to count primes
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//function to find primes
int is_prime(int n) {
if (n < 2)return 0;
if (n == 2)return 1;
if (n % 2 == 0)return 0;
for (int i=3; i < n; i += 2) {
if (n % i == 0) return 0;
}
return 1;
}
void *PrintPrimes(void *threadid) {
int thread_start, thread_end;
int thread_id = (int)threadid; //store thread id in thread_id
thread_start = thread_id*(NUM_COUNT/NUM_THREADS); //determine where individual thread begins searching for primes
thread_end = thread_start+(NUM_COUNT/NUM_THREADS); //determine where thread ends searching for primes
for(int n = thread_start; n < thread_end; n++) {
if (is_prime(n)) {
pthread_mutex_lock(&mutex);
counter++;
printf("the number of primes is currently %d\n", counter);
pthread_mutex_unlock(&mutex);
}
}
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
for(int i = 0; i < NUM_THREADS; i++){
pthread_create(&threads[i], NULL, PrintPrimes, (void *)i);
}
pthread_exit(NULL);
}
我发现代码有一些问题:
您永远不会在线程上调用
pthread_join()
,这意味着您的程序将在生成线程后立即退出,而不是等待它们完成——这可能不是您想要的。您应该在main()
函数的底部添加第二个像这样的 for 循环:for(int i = 0; i < NUM_THREADS; i++) { pthread_join(&threads[i], NULL); }
main()
中对pthread_exit()
的调用是不必要的,可以去掉。 (它意味着从生成的 pthread 中调用以导致线程退出,没有必要从主线程调用它)从线程的计算循环中调用
printf()
会大大减慢计算速度(以至于您根本不再测量实际计算的性能) ,而您实际上只是在测量printf()
和 stdout 子系统执行的速度)每次找到一个新的质数时都必须用互斥锁来保护 shared/global
counter
效率不是很高;最好为每个线程声明一个 local/non-shared 计数器变量,并递增它。然后在线程执行结束时,您可以将线程的本地计数器添加到 shared/global 计数器一次,从而避免更多地支付 lock()/unlock() 序列带来的同步惩罚每个线程不止一次。