多线程求解5千万内有多少个质数?

博客介绍了C++单线程与多线程的解法。单线程运行代码时,实际运行时间约等于用户态与系统态时间之和,4核Mac仅用一个核。多线程编译需 -pthread 选项以启用线程支持,可通过修改别名简化,多线程实际运行时间更短,单个核用时约为用户态时间的1/4 - 1/5。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单线程的解法

如下:

#include <iostream>

using namespace std;

static bool isPrime(int num)
{
    if (num == 1)
    {
        return false;
    }

    if ((num == 2) || (num == 3))
    {
        return true;
    }
    
    int mod = num % 6; 
    if ((mod != 1) && (mod != 5))
    {
        return false;//不是6的倍数±1的,都不是质数。
    }
    else
    {
        for(int j = 2; j * j <= num; ++j)
        {
            if (num % j == 0)
            {
                return false;
            }
        }
        return true;
    }
}

int main()
{
    int cnt = 0;
    for(int i = 0; i <= 50000000; ++i)
    {
        if(isPrime(i))
        {
            ++cnt;
        }
    }
    cout << "cnt is " << cnt << endl; // 3001134,单线程时间是48秒
    return 0;
}

结果是:

cnt is 3001134

real	0m48.490s
user	0m47.457s
sys	0m0.235s

可以看到单线程情况下,实际运行时间是48秒,约等于用户态占的时间和系统态占的时间之和。
我的Mac是4核的,此时只用了一个核来运行代码。

多线程的解法

需要使用的编译方法是

g++ -std=c++11 -pthread xxx.cpp
time a.out

-pthread 是一个编译选项,它用于启用 C++ 中的线程支持。
在 C++ 中,使用多线程需要在编译时链接线程库。-pthread 选项告诉编译器在链接阶段链接到 POSIX 线程库( pthread ),以便你可以在代码中使用线程相关的功能。
没有 -pthread 选项,你可能无法在代码中使用多线程,或者可能会遇到链接错误。
当你使用 -pthread 选项时,编译器会将线程库的代码包含到你的程序中,并生成可以使用线程的可执行文件。
当然可以通过修改别名alias的方式,简化一下。具体步骤如下:

vi ~/.bash_profile
在打开的文件中,您可以添加类似如下的内容来设置别名:
alias g++='g++ -std=c++11 -pthread'

多线程的代码如下:

#include <iostream>
#include <thread>
#include <mutex>

using namespace std;


static bool isPrime(int num)
{
    if (num == 1)
    {
        return false;
    }

    if ((num == 2) || (num == 3))
    {
        return true;
    }
    int mod = num % 6; 
    if ((mod != 1) && (mod != 5))
    {
        return false;//不是6的倍数±1的,都不是质数。
    }
    else
    {
        for(int j = 2; j * j <= num; ++j)
        {
            if (num % j == 0)
            {
                return false;
            }
        }
        return true;
    }
}

int cnt = 0;
mutex mtx;

void worker(int left, int right)
{
    unique_lock<mutex> lckBegin(mtx);//打印要加锁,否则线程间有干扰
    cout << this_thread::get_id() << ": begin()" << endl;
    lckBegin.unlock();

    for(int i = left; i < right; ++i)
    {
        if (isPrime(i))//该函数不能放在锁里,否则严重影响效率。
        {
            unique_lock<mutex> lck(mtx);
            ++cnt;//不加锁结果会错误
            lck.unlock();
        }
    }

    unique_lock<mutex> lckEnd(mtx);
    cout << this_thread::get_id() << ": end()" << endl;
    lckEnd.unlock();
}

int main()
{
    const int batch = 5000000;//5百万
    thread* trr[10];
    for(int i = 0, j = 1; i < 10; ++i, j += batch)
    {
        trr[i] = new thread(worker, j, j + batch);
    }

    for(int i = 0; i < 10; ++i)
    {
        trr[i]->join();
    }

    for(auto x : trr)
    {
        delete x;
    }
    cout << "cnt is " << cnt << endl; // 3001134
    return 0;
}

结果是:

zhanghaodeMacBook-Pro:cpp_excise zhanghao$ time ./a.out 
0x70000a3e7000: begin()
0x70000a46a000: begin()
0x70000a7ff000: begin()
0x70000a882000: begin()
0x70000a5f3000: begin()
0x70000a676000: begin()
0x70000a6f9000: begin()
0x70000a77c000: begin()
0x70000a4ed000: begin()
0x70000a570000: begin()
0x70000a3e7000: end()
0x70000a46a000: end()
0x70000a4ed000: end()
0x70000a570000: end()
0x70000a5f3000: end()
0x70000a676000: end()
0x70000a6f9000: end()
0x70000a77c000: end()
0x70000a7ff000: end()
0x70000a882000: end()
cnt is 3001134

real	0m13.397s
user	1m21.319s
sys	0m0.381s

real 指实际运行时间,为13秒(每个核的大概时间)。
用户态时间为81秒。
我的Mac是四核的。可以看到,单个核所用的时间是用户态时间的大约1/4~1/5。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码到程攻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值