- Mastering Concurrency in Python
- Quan Nguyen
- 434字
- 2021-06-10 19:23:54
Example 2 – inherently sequential tasks
Let us consider a quick example:
Computing f1000(3), with f(x) = x2 - x + 1, and fn + 1(x) = f(fn(x)).
With complicated functions like f (where it is relatively difficult to find a general form of fn(x)), the only obviously reasonable way to compute f1000(3) or similar values is to iteratively compute f2(3) = f( f(3)), f3(3) = f( f2(3)), ... , f999(3) = f( f998(3)), and, finally, f1000(3) = f( f999(3)).
Since it will take significant time to actually compute f1000(3), even when using a computer, we will only consider f20(3) in our code (my laptop actually started heating up after f25(3)):
# Chapter01/example2.py
def f(x):
return x * x - x + 1
# sequential
def f(x):
return x * x - x + 1
start = timer()
result = 3
for i in range(20):
result = f(result)
print('Result is very large. Only printing the last 5 digits:', result % 100000)
print('Sequential took: %.2f seconds.' % (timer() - start))
Run it (or use python example2.py); the following code shows the output I received:
> python example2.py
Result is very large. Only printing the last 5 digits: 35443
Sequential took: 0.10 seconds.
Now, if we were to attempt to apply concurrency to this script, the only possible way would be through a for loop. One solution might be as follows:
# Chapter01/example2.py
# concurrent
def concurrent_f(x):
global result
result = f(result)
result = 3
with concurrent.futures.ThreadPoolExecutor(max_workers=20) as exector:
futures = [exector.submit(concurrent_f, i) for i in range(20)]
_ = concurrent.futures.as_completed(futures)
print('Result is very large. Only printing the last 5 digits:', result % 100000)
print('Concurrent took: %.2f seconds.' % (timer() - start))
The output I received is shown as follows:
> python example2.py
Result is very large. Only printing the last 5 digits: 35443
Concurrent took: 0.19 seconds.
Even though both methods produced the same result, the concurrent method took almost twice as long as the sequential method. This is due to the fact that every time a new thread (from ThreadPoolExecutor) was spawned, the function conconcurrent_f(), inside that thread, needed to wait for the variable result to be processed by the previous thread completely, and the program as a whole was thus executed in a sequential manner, nonetheless.
So, while there was no actual concurrency involved in the second method, the overhead cost of spawning new threads contributed to the significantly worse execution time. This is one example of inherently sequential tasks, where concurrency or parallelism should not be applied to attempt an improvement in execution time.
- 數(shù)據(jù)庫(kù)程序員面試筆試真題與解析
- Unity 2020 Mobile Game Development
- 程序員面試算法寶典
- Python機(jī)器學(xué)習(xí)經(jīng)典實(shí)例
- Big Data Analytics
- D3.js 4.x Data Visualization(Third Edition)
- Nginx Lua開(kāi)發(fā)實(shí)戰(zhàn)
- ExtJS Web應(yīng)用程序開(kāi)發(fā)指南第2版
- Java并發(fā)編程之美
- Mastering SciPy
- R的極客理想:量化投資篇
- 數(shù)字媒體技術(shù)概論
- Java多線(xiàn)程并發(fā)體系實(shí)戰(zhàn)(微課視頻版)
- ANSYS FLUENT 16.0超級(jí)學(xué)習(xí)手冊(cè)
- Android 5從入門(mén)到精通