21

I searched everywhere and I don't find any simple example of iterating a loop with multithreading.

For example, how can I multithread this loop?

for item in range(0, 1000):
    print(item)

Is there any way to cut it in like 4 threads, so each thread has 250 iterations?

3 Answers 3

27

Easiest way is with multiprocessing.dummy (which uses threads instead of processes) and a Pool

import multiprocessing.dummy as mp 

def do_print(s):
    print s

if __name__=="__main__":
    p=mp.Pool(4)
    p.map(do_print,range(0,10)) # range(0,1000) if you want to replicate your example
    p.close()
    p.join()

Maybe you want to try real multiprocessing, too if you want to better utilize multiple CPUs but there are several caveats and guidelines to follow then.

Possibly other methods of Pool would better suit your needs - depending on what you are actually trying to do.

Sign up to request clarification or add additional context in comments.

12 Comments

Thanks! What if I need to pass other arguments to the do_print function?
that depends - with multiprocessing.dummy there should be no problems but if you want to make sure you should put the args in the iterable - eg with zip or list comprehensions
For some reason, this code creates about 60 (!) threads to iterate over range(0, 1000) for me (Python 3.5)...
@janbrohl: To avoid unnecessary temporaries, you'd want to use the Py3's zip (on Py2, replace bad zip with good zip using from future_builtins import zip) or a generator expression, so the arguments are produced lazily (as needed) instead of eagerly (delaying dispatch of first call and wasting memory).
@ForceBru: If you used multiprocessing.dummy, that should be impossible; the Pool constructor given is only using four worker threads.
|
10

You'll have to do the splitting manually:

import threading

def ThFun(start, stop):
    for item in range(start, stop):
        print item

for n in range(0, 1000, 100):
    stop = n + 100 if n + 100 <= 1000 else 1000
    threading.Thread(target = ThFun, args = (n, stop)).start()

This code uses multithreading, which means that everything will be run within a single Python process (i.e. only one Python interpreter will be launched).

Multiprocessing, discussed in the other answer, means running some code in several Python interpreters (in several processes, not threads). This may make use of all the CPU cores available, so this is useful when you're focusing on the speed of your code (print a ton of numbers until the terminal hates you!), not simply on parallel processing. 1


1. multiprocessing.dummy turns out to be a wrapper around the threading module. multiprocessing and multiprocessing.dummy have the same interface, but the first module does parallel processing using processes, while the latter - using threads.

6 Comments

multiprocessing.dummy actually uses threads - edited my answer to make that more clear
multiprocessing.dummy is indeed a wrapper around the threading module, but multiprocessing itself works exactly as described in the crossed-out part of the answer. Which one is chosen depends on what behavior one wants, the code is the very same (that's a good thing).
@miraculixx, this is why I decided not to remove the now crossed-out part completely: multiprocessing and multiprocessing.dummy have similar interfaces, but the choice of a module affects the behavior (threads vs processes).
@ForceBru I see, the problem is that it now looks as though what you wrote is incorrect, which it isn't, possibly confusing someone looking for multiprocessing ... multiprocessing and multiprocessing.dummy have the exact same interface, that's the whole point.
@miraculixx: Not exactly, but close enough, and they try to keep them consistent. multiprocessing.dummy accidentally omitted the cpu_count function for example.
|
6

Since Python 3.2, the concurrent.futures standard library provides primitives to concurrently map a function across iterables. Since map and for are closely related, this allows to easily convert a for loop into a multi-threaded/multi-processed loop:

from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor() as executor:
    executor.map(print, range(0, 1000))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.