-
Notifications
You must be signed in to change notification settings - Fork 344
thread_example_1
Two threads will be created, performing simple arithmetic operations.
Both threads will use the same function, but with different arguments.
First, we need to import the needed modules and create the thread function:
import machine, time, _thread
# Both threads will use the same function
def th_func(tmr):
x = 0
f = 1.1
ntf = 0
tm = 0
n = 100000
start_time = 0
end_time = 0
myname = _thread.getSelfName()
# Init the thread timer
t = machine.Timer(tmr)
t.init(mode=t.CHRONO)
while True:
ntf = _thread.wait()
if ntf == _thread.EXIT:
# Terminate the thread
return
elif ntf > 0 and ntf < 5:
# Start the instruction loop
if (ntf == 2) or (ntf == 4):
# For commands 2 and 4
# Lock the thread, other threads will not execute
_thread.lock()
# Get start time and start the timer
start_time = time.ticks_us()
t.start()
if ntf < 3:
# For commands 1 and 2 run integer addition test
for i in range(0, n):
x += 1
else:
# For commands 3 and 4 run float multiplication test
for i in range(0, n):
f *= 1.2345
# Stop the timer and get the end time
t.stop()
end_time = time.ticks_us()
if (ntf == 2) or (ntf == 4):
# Unlock the thread, other threads can now run
_thread.unlock()
# Get the elapsed time
tm = t.value()
elif ntf == 7:
# Print the operation summary
print("[{}] Elapsed: {} us ({:.3f} us inst time) , start: {}, end: {}".format(myname, tm, tm/n, start_time, end_time))
tm = 0
start_time = 0
end_time = 0
At start, the thread function initializes some local variables and creates a timer for measuring the elapsed times.
The timer used is determined from the function argument.
After the initialization, the function executes the infinite loop.
_thread.wait()
is executed which puts the thread into waiting state for infinite time. During the wait, the function uses no resources.
When a notification is received, the function continues the execution and check the notification value:
- if
_thread.EXIT
notification is received, the function returns, terminating the thread - if notification
7
is received, the results from the last command are printed. - if notifications
1
-4
are received, they are interpreted as commands-
1
&2
execute 100000 integer additions and measure the execution time -
3
&4
execute 100000 float multiplications and measure the execution time - for commands
2
&4
lock the thread (prevent other threads from running) while executing the command loop
-
Start the threads and list the the running threads:
>>> th1 = _thread.start_new_thread("THRD#1", th_func, (1,))
>>> th2 = _thread.start_new_thread("THRD#2", th_func, (2,))
>>>
>>> _thread.list()
ID=1073586276, Name: THRD#2, State: waiting, Stack=4096, MaxUsed=948, Type: PYTHON
ID=1073581228, Name: THRD#1, State: waiting, Stack=4096, MaxUsed=956, Type: PYTHON
ID=1073447944, Name: MainThread, State: running, Stack=20480, MaxUsed=2616, Type: MAIN
Request single thread to run the addition test:
_thread.notify(th1, 1)
True
#wait some time
time.sleep_ms(1000)
#request the result
_thread.notify(th1, 7)
True
>>> [THRD#1] Elapsed: 334714 us (3.347 us inst time) , start: 92310422, end: 92645235
The execution time was ~33.5 ms.
Now, request both thread to run the addition test, both thread will run simultaneously:
(Using 0
as thread ID argument in _thread.notify()
will send the notification to all running threads.
)
>>> _thread.notify(0, 1)
True
#wait some time
time.sleep_ms(1000)
#request the result
_thread.notify(0, 7)
True
>>>
[THRD#2] Elapsed: 685324 us (6.853 us inst time) , start: 2970786146, end: 2971471567
[THRD#1] Elapsed: 683008 us (6.830 us inst time) , start: 2970786357, end: 2971469397
As expected, the elapsed time is approximately double than for a single thread (~68.4 ms) and both threads started the command at approximately the same time.
Now, request both thread to run the addition test, but request that the thread locks during the calculation loop:
>>> _thread.notify(0, 2)
True
#wait some time
time.sleep_ms(1000)
#request the result
_thread.notify(0, 7)
True
>>>
>>>
[THRD#2] Elapsed: 284342 us (2.843 us inst time) , start: 3737026856, end: 3737311298
[THRD#1] Elapsed: 284279 us (2.843 us inst time) , start: 3737311489, end: 3737595798
We can see that the total execution time and calculation time are somewhat lower (~56.9 / ~28.4 ms) than with both thread running simultaneously due to fact that the main thread was blocked during the calculation loop in both threads.
Note that the th2 has started first, blocked during the calculation, then th1 started when th2 unblocked.
The similar tests can be run with float multiplication:
>>> _thread.notify(0, 4)
True
>>> _thread.notify(0, 7)
True
>>>
[THRD#2] Elapsed: 574453 us (5.745 us inst time) , start: 4390469846, end: 4391044408
[THRD#1] Elapsed: 641261 us (6.413 us inst time) , start: 4391044554, end: 4391685956
>>> _thread.notify(0, 3)
True
>>> _thread.notify(0, 7)
True
>>>
[THRD#2] Elapsed: 1348498 us (13.485 us inst time) , start: 4420614908, end: 4421963510
[THRD#1] Elapsed: 1317523 us (13.175 us inst time) , start: 4420615437, end: 4421933080