简体   繁体   中英

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). 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?

Here's a screenshot from my macOS machine, running your program:

在此处输入图像描述

And here, a screenshot from htop on a Linux virtual machine:

在此处输入图像描述

In other words, your program will happily consume as much of a single CPU core as it can, as it's single-threaded.

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.

Happily, that's where the multiprocessing module steps in; it orchestrates multiple separate Python processes that aren't encumbered by a shared lock. You can see that this program is already quite a bit more complex, but does manage to saturate all 16 cores on my machine.

在此处输入图像描述

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.

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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