繁体   English   中英

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

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

我写了一个简单的 python 代码,它只是不停地打印素数,但它只使用了我笔记本电脑 CPU 的 25%(100% 的单核)。 但我希望它使用所有的核心。 那可能吗? 顺便说一句,这里是代码:

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

这就引出了一个问题:你是如何测量你的程序使用了多少 CPU 的?

这是我的 macOS 机器的屏幕截图,运行您的程序:

在此处输入图像描述

这里是 Linux 虚拟机上的htop屏幕截图:

在此处输入图像描述

换句话说,您的程序将愉快地消耗尽可能多的单个 CPU 内核,因为它是单线程的。

编辑

为了使您的程序使用普通的 Python 消耗所有内核,不幸的是,由于全局解释器锁 (GIL)使得基于 Python 的并行 CPU 工作效率非常低,因此线程不会不幸地切断它。

令人高兴的是,这就是multiprocessing模块介入的地方; 它协调多个不受共享锁阻碍的独立 Python进程 你可以看到这个程序已经相当复杂了,但确实设法使我机器上的所有 16 个内核饱和。

在此处输入图像描述

由于工人们查看的是 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