【问题标题】:multi-threaded prime generator多线程素数生成器
【发布时间】:2026-01-08 21:50:01
【问题描述】:

我目前正在研究这个多线程素数生成器,它计算 2 - N 范围内的素数数量,目前每个线程都计算所有素数,看起来线程正在运行一个之后另一个,但我希望所有线程同时运行。

现在我想问一下如何告诉线程它应该只计算切片大小,而不是所有素数,并且“t”线程同时运行。

例如:2-1000 四个线程 -> 每个线程应该计算 250 个数字

提前致谢!

这是我目前拥有的:

#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

/* compile: gcc prime.c -lpthread -o prime */
/* execute: ./prime -N 1000 -t 8 */

pthread_mutex_t aktuell_lock = PTHREAD_MUTEX_INITIALIZER;


int N;
int Primzahlen;

int aktuell = 2;
int t;
//int slicesize = N/t;


void print_usage(void)
{
    printf("Usage: prime -N <value> -t <value>\n");
}

void *prime(void *a)
    {

    int Laufvariable;

    int i;

    pthread_mutex_lock(&aktuell_lock);
    for (i = 0; i < N/t; i++) {

    for (aktuell; aktuell <= N; aktuell++) {

    for (Laufvariable = (aktuell-1); aktuell % Laufvariable; Laufvariable--) {
    }

    if (Laufvariable == 1)
        Primzahlen++;
    }
    }
    pthread_mutex_unlock(&aktuell_lock);
        return NULL;
    }

int main(int argc, char *argv[])
{
    struct timespec start, finish;
    double elapsed;

    clock_gettime(CLOCK_MONOTONIC, &start);

    int s;
    int option;

    while ((option = getopt(argc, argv, "N:t:")) != -1)
        switch (option) {
        case 'N':
            N = atoi(optarg);
                break;
        case 't':
            t = atoi(optarg);
                break;
        default:
            print_usage();
            exit(EXIT_FAILURE);
        }
    pthread_t threads[t];

    for (s = 0; s < t; s++) {
        pthread_create(&threads[t], NULL, prime, NULL);
    }

    void *result;

    for (s = 0; s < t; s++) {
        pthread_join(threads[t], &result);
    }
    clock_gettime(CLOCK_MONOTONIC, &finish);

    elapsed = (finish.tv_sec - start.tv_sec);
    elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;

    printf("\nCount Primes [1 .. %d] - TaskCnt: %d - Slicesize: %d\n", N, t, N / t);
    printf("Threads: %d\n", t);
    printf("limit: %d\n", N);
    printf("Total Prime Count: %d\n", Primzahlen);
    printf("Runtime: %f seconds\n\n", elapsed);

    return 0;
}

【问题讨论】:

  • 使用线程的问题是,最快的方法是只用你已经证明的素数来测试除法。这样一个线程将比测试每个(奇数)除数的 4 个线程快。
  • 你应该提供一些示例代码来展示你如何管理你的线程
  • 将不同的范围作为函数参数传递给每个 pthreat 并丢弃互斥锁。你需要重写 pthread 函数
  • 现在您已经发布了一些代码,它所做的工作远远超出了它的需要。检查偶数,然后检查从3...+=2 到数字平方根的奇数除数。更好的是,只需检查您已经找到的素数作为除数。

标签: c multithreading posix primes


【解决方案1】:

使用锁进行并行处理绝对不会妨碍程序的可扩展性。

不要在锁下的全局变量中累积结果和状态,而是尝试累积部分线程特定的结果,然后合并它们。

distribution 中有一个现成的可扩展素数计数器示例。如果需要,您可以直接使用它,也可以采用工作范围划分和减少部分结果的想法,并在纯 C 中实现它。

【讨论】:

    【解决方案2】:

    您可以分阶段执行此操作。最简单的版本使用单个线程生成素数数组,直到 prime(i) * prime(i) >= N。设置 R = N-prime(i),这是要测试的数字范围。那么thread[j](j从0开始)应该从prime(i)+j * (R/t)测试到prime(i)+(j+1) * (R/t),最后一个线程测试从prime(i)+j * (R/t) 到 N(t 是线程数)。每个线程都会生成自己的计数,一旦所有线程完成,计数就会相加。

    每个线程也可以生成它自己的素数范围,一旦所有线程完成,数组就会连接起来。这可以扩展到经过多次传递,例如从 2 到 100 查找素数,使用线程查找从 100 到 1000 的素数,连接数组,查找从 1000 到 1000000 的素数,...。

    【讨论】: