简体   繁体   English

为什么我的 python 代码没有使用所有的 cpu?

[英]why isn't my python code using all of the cpu?

i wrote a simple python code that just prints prime numbers nonstop but it only uses 25% percent of my laptops cpu (100% of a single core).我写了一个简单的 python 代码,它只是不停地打印素数,但它只使用了我笔记本电脑 CPU 的 25%(100% 的单核)。 but i want it to use all of the cores.但我希望它使用所有的核心。 is that possible?那可能吗? BTW here is the code:顺便说一句,这里是代码:

x = 10
while True:
    for num in range(1, x):
        flag = False
        if x > 1:
            for i in range(2, x):
                if (x % i) == 0:
                    flag = True
                    break
        if not flag:
            print(x, "is a prime number")
            break
    x += 1

This begs the question: how did you measure how much CPU your program uses?这就引出了一个问题:你是如何测量你的程序使用了多少 CPU 的?

Here's a screenshot from my macOS machine, running your program:这是我的 macOS 机器的屏幕截图,运行您的程序:

在此处输入图像描述

And here, a screenshot from htop on a Linux virtual machine:这里是 Linux 虚拟机上的htop屏幕截图:

在此处输入图像描述

In other words, your program will happily consume as much of a single CPU core as it can, as it's single-threaded.换句话说,您的程序将愉快地消耗尽可能多的单个 CPU 内核,因为它是单线程的。

EDIT编辑

To make your program consume all of your cores with plain Python, just threads won't unfortunately cut it due to the Global Interpreter Lock (GIL) making Python-based parallel CPU work quite inefficient.为了使您的程序使用普通的 Python 消耗所有内核,不幸的是,由于全局解释器锁 (GIL)使得基于 Python 的并行 CPU 工作效率非常低,因此线程不会不幸地切断它。

Happily, that's where the multiprocessing module steps in;令人高兴的是,这就是multiprocessing模块介入的地方; it orchestrates multiple separate Python processes that aren't encumbered by a shared lock.它协调多个不受共享锁阻碍的独立 Python进程 You can see that this program is already quite a bit more complex, but does manage to saturate all 16 cores on my machine.你可以看到这个程序已经相当复杂了,但确实设法使我机器上的所有 16 个内核饱和。

在此处输入图像描述

Since the workers look at different parts of the integer range, the results printed by this program won't be in strict order at all.由于工人们查看的是 integer 范围的不同部分,因此该程序打印的结果将完全没有严格的顺序。

import multiprocessing
import queue
from itertools import count


def is_prime(x):
    for i in range(2, x // 2 + 1):
        if x % i == 0:
            return False
    return True


def prime_loop(result_queue: multiprocessing.Queue, start: int, step: int):
    for i in count(start, step):
        if is_prime(i):
            result_queue.put((i, True))


def main():
    result_queue = multiprocessing.Queue()
    num_workers = multiprocessing.cpu_count()
    workers = []
    for i in range(num_workers):
        # Since there's no point in starting a worker that would look at even numbers,
        # we start the first worker at 1 and the second worker at 3, etc.
        start = i * 2 + 1
        # Each worker will step over by the number of workers + 1, so e.g. if there are 4 workers,
        # worker 1 will check 1, 5, 11, 16,
        # worker 2 will check 2, 6, 12, 17,
        # worker 3 will check 3, 7, 13, 18,
        # worker 4 will check 4, 8, 14, 19 etc.
        step = num_workers + 1
        worker = multiprocessing.Process(
            target=prime_loop, args=(result_queue, start, step)
        )
        worker.start()
        workers.append(worker)
    seen = set()
    while True:
        try:
            number, result = result_queue.get(timeout=0.1)
            if result:
                if number in seen:
                    raise NotImplementedError("bug :(")
                seen.add(number)
                print(f"{number} is a prime number")
        except KeyboardInterrupt:
            break
        except (multiprocessing.TimeoutError, queue.Empty):
            pass
    for worker in workers:
        worker.kill()


if __name__ == "__main__":
    main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM