How to synchronize the start time of python threads? - python

I want to measure the time delay of a signal. To do that the signal is put on a speaker an the delay when it gets captured by a microphone is estimated. The delay is expected to be in the range of milliseconds, so it is crucial to start the speaker signal and the measurement at the exact same time.
My question is if that can be achieved by using threads:
def play_sound():
# play sound
def record():
# start recording
if __name__ == '__main__':
t1 = threading.Thread(target=play_sound())
t2 = threading.Thread(target=record())
t1.start()
t2.start()
or is there a better way to d it?

I would start the recording thread first and look for the first peak in the signal captured by the mic. This will tell you how many ms after recording started the first sound was detected. For this you probably need to know the sampling rate of the mic etc- here is a good starting point.
The timeline is something like this
---- recording start ------- playback start -------- sound first detected ----
You want to find out how many ms after you start recording a sound was picked up ((first_peak - recording_start) in the code below), and then subtract the time it took to start the playback ((playback_start - recording_start) below)
Here's a rough code outline
from datetime import datetime
recording_start, playback_start, first_peak = None, None, None
def play_sound():
nonlocal playback_start
playback_start = datetime.now()
def record():
nonlocal recording_start, first_peak
recording_start = datetime.now()
first_peak = find_peak_location_in_ms() # implement this
Thread(target=record()).start() # note recording starts first
Thread(target=play_sound()).start()
# once the threads are finished
delay = (first_peak - recording_start) - (playback_start - recording_start)
PS one of the other answers correctly points out that you need to worry about the global interpreter lock. You can likely bypass it by using c-level APIs to record/play the sound without blocking other threads, but you may find Python's not the right tool for that job

It won't be 100% concurrent real-time, but no solution for desktop will ever be. The question then becomes if it is accurate enough for your application. To know this you should simply run a few tests with known delays and see if it works.
You should know about the global interpreter lock: https://docs.python.org/3.3/glossary.html#term-global-interpreter-lock. This means that even on a multicore pc you code won't run truly concurrent.
If this solution is not accurate enough, you should look into the multiprocessing package. https://docs.python.org/3.3/library/multiprocessing.html
Edit: Well, in order to truly get them to start simultaneously you can't start them sequentially after each other like that. You need to use multiprocessing, create the two threads, and then create some kind of interrupt that will start the two threads at the same time. And I think even then you can't be truly sure they will start at the same time because the OS can switch in other stuff (multitasking), and even if that goes fine in the processors itself things might be reordered differently, different code might be cached, etc. On a desktop you can never have the guarantuee that two programs start simultaneously. So the question then becomes if they are consistently simultaneous enough for your purpose. To answer that you will need to find someone with experience in this, or just run a few tests.

Related

Running two files on a single project on PyCharm

I am currently developing a IoT sensor value simulator using the PyCharm IDE (along with pygame). Essentially, I am trying to produce/send data to Microsoft Azure IoT platform while there is a GUI available for users, in which they can see the temperatures of each sensor, change the sensor outputs, etc.
Since I do not want to spam Azure with messages, I use sleep function between every messages sent to limit the rate of messages being sent. As a result, this slows down the whole application and it is a bit cumbersome. Is there a way to get around this where I can send messages without affecting the user experience on the GUI? Thanks!
As Ted pointed out, multithreading is definitely an option, but may be a bit overkill depending on your case.
As an alternative solution you can use the time module of python to calculate the time since the last message was sent and only send a new message if enough time has passed. This way your other processes will continue to run as expected and you don't have to sleep / freeze your program.
import time
start = time.time()
message_interval = 5 # in seconds
while True:
# other application logic
if time.time() - start >= message_interval:
send_message()
start = time.time() # reset timer
You could potentially even combine it with another check to see if it is even necessary to send a message.
import time
start = time.time()
message_interval = 5 # in seconds
update_available = true
while True:
if time.time() - start >= message_interval and update_available:
send_update_message()
start = time.time() # reset timer
update_available = false # reset variable
they mention in the Docs a debugger which you can run locally

How to check cpu consumption by a python script

I have implemented kalman filter. I want to find out how much of cpu energy is being consumed by my script. I have checked other posts on Stackoverflow and following them I downloaded psutil library. Now, I am unaware of where to put the statements to get the correct answer. Here is my code:
if __name__ == "__main__":
#kalman code
pid = os.getpid()
py = psutil.Process(pid)
current_process = psutil.Process();
memoryUse = py.memory_info()[0]/2.**30 # memory use in GB...I think
print('memory use:', memoryUse)
print(current_process.cpu_percent())
print(psutil.virtual_memory()) # physical memory usage
Please inform whether I am headed in the right direction or not.
The above code generated following results.
('memory use:', 0.1001129150390625)
0.0
svmem(total=6123679744, available=4229349376, percent=30.9, used=1334358016, free=3152703488, active=1790803968, inactive=956125184, buffers=82894848, cached=1553723392, shared=289931264, slab=132927488)
Edit: Goal: find out energy consumed by CPU while running this script
​
I'm not sure whether you're trying to find the peak CPU usage during execution of that #kalman code, or the average, or the total, or something else?
But you can't get any of those by calling cpu_percent() after it's done. You're just measuring the CPU usage of calling cpu_percent().
Some of these, you can get by calling cpu_times(). This will tell you how many seconds were spent doing various things, including total "user CPU time" and "system CPU time". The docs indicate exactly which values you get on each platform, and what they mean.
In fact, if this is all you want (including only needing those two values), you don't even need psutils, you can just use os.times() in the standard library.
Or you can just use the time command from outside your program, by running time python myscript.py instead of python myscript.py.
For others, you need to call cpu_percent while your code is running. One simple solution is to run a background process with multiprocessing or concurrent.futures that just calls cpu_percent on your main process. To get anything useful, the child process may need to call it periodically, aggregating the results (e.g., to find the maximum), until it's told to stop, at which point it can return the aggregate.
Since this is not quite trivial to write, and definitely not easy to explain without knowing how much familiarity you have with multiprocessing, and there's a good chance cpu_times() is actually what you want here, I won't go into details unless asked.

Python 1 second clock timer

I have a Threaded timer that fires every second and updates a clock, the problem is that sometimes the clock will appear to be unstable and it can jump 2 seconds instead of a steady 1 second increment.
The problem of course is that the initial (or subsequent) timer is not triggered at exactly 0:000 seconds and therefore it is possible that updates to the clock appear to jitter.
Is there any way of preventing this ?
from threading import Timer
def timer():
Timer(1.00, timer).start()
STAT['ftime'] = time.strftime("%H:%M:%S")
start_time = time.time()
interval = 1
for i in range(20):
time.sleep(start_time + i*interval - time.time())
# do a thing
Replace '20' with however many seconds you want to time.
There are various approaches how to schedule, some designs may even provide measures to be able to deliver some acceptable kind of remedy for a blocked / failed initiation on a planned scheduling time-line -- what may help is finer timing / hierarchical timing / external synchronisation / asynchronous operations.
Without more details, there would be a poor practice to "recommend", but one may get ispired:
if RealTime constraints allow to bear a bit more overhead, one may go to a "supersampled" elastic, failure-resilient scheduling scenario, so as to avoid a 2 second gap ( in case of a failed one .Timer() initiation ), where threading.Timer() model fires each 50 msec, and an embedded logic decides, if it is the right-time ( not farther than a half of one scheduling interval from an idealised one second edge ) and does the real-job, that was intended to be run, or just return, in case the RTC is not "near" the planned idealised scheduling time.
a good python design also cannot forget about problems with GIL-lock issues, with avoiding blockingIO(s), with implementing a reasonable task-segmentation for CPU-bound parts of the code

How to set an multiple alarm in python

I want to set multiple alarm in python. What is the recommended way of setting it up? My use-case is that I've threshold time for N variables. When the current time reaches the threshold value, I want all the variables with that threshold values.
Here's my apprach:-
threshold_time_list = [get list all times from the DB]
current_time = datetime.now()
[i for i in threshold_time_list if i==current_time]
But this is very inefficient way of doing it since I might have 250+ variables like a/b/c.
And also I have to check this condition every second(cronjob). Is there a better way of doing it?
I found on SO, this can be done using threading and making the thread to go to sleep for threshod - current_time. But running 250 threads parallely is again an issue, since I've been facing an issue in my production where Django gets hanged (dont know why) and I need to restart the server to make it work again. We're asssuming that Django might get out of threads for processing, hence making 250 more threads is cumbersome.
Also if someone knows , why does Django gets hang in b/w the running live product it will be beneficial.
Can this alarm question be done in celery?
Use the sched module. This lets you create any number of scheduled tasks, then run them when they kick off, one at a time.

time.sleep and suspend (ie. standby and hibernate)

For example, if I do time.sleep(100) and immediately hibernate my computer for 99 seconds, will the next statement be executed in 1 second or 100 seconds after waking up?
If the answer is 1 second, how do you "sleep" 100 seconds, regardless of the length of hibernate/standby?
time.sleep(N) attempts to sleep at least N seconds of elapsed, AKA "wall-clock" time - of course there can be no guarantee that the sleep will last exactly N seconds; for example, the thread becomes ready to execute again at that time, but it cannot necessarily preempt whatever other thread is executing at that time -- that's the operating system's decision to make, not any programming language's; on the other hand, sleep may be prematurely interrupted by various kinds of events (such as interrupts).
If you can find on your operating system some clock-like thingy that only advances when the system's state is the one you care about (e.g. "not hybernated", in your case), then of course you can go back to sleep if you wake up again "too early".
For example, on Windows 7, QueryUnbiasedInterruptTime is specifically documented to "not include time the system spends in sleep or hibernation" and to use units of 100 nanoseconds. So if you call that, e.g. through ctypes, you can achieve the effect you want:
def unbiasedsleep(n):
start = kernel32.QueryUnbiasedInterruptTime()
target = start + n * 10 * 1000 * 1000
while True:
timeleft = target - kernel32.QueryUnbiasedInterruptTime()
if timeleft > 0:
time.sleep(timeleft / (10 * 1000 * 1000.0))
I don't know how to get the equivalent of QueryUnbiasedInterruptTime on other releases of Windows or other operating systems, but then, you don't tell us what operating system(s) you're interested in, so it would be pretty pointless anyway to present a long laundry lists of approaches which may work similarly in different environments.
I don't know exactly what you are trying to achieve, but
for i in range(100):sleep(1)
might work, as the hibernate would only use up to 1 seconds worth of the sleep
Clearly, you must sleep according to real, elapsed time.
The alternative (sleeping according to some other clock that "somehow" started and stopped) would be unmanageable. How would your application (which is sleeping) be notified of all this starting and stopping activity? Right, it would have to be woken up to be told that it was not supposed to run because the system was hibernating.
Or, perhaps, some super-sophisticated OS-level scheduler could be used to determine if some time the system was "busy" vs. "hibernating" counted against the schedules of various sleeping processes.
All too complex.
Indeed, if you check carefully, sleep is pretty approximate and any Unix Signal will interrupt it. So it's possible to wake early for lots of reasons. Control-C being the big example.

Categories

Resources