Thursday 16 November 2017

When your problem is life ... and that infinitely repeating operation you programmed months ago

All right all right, I am the first to admit that in the grand scheme of things my programming ability is only slightly higher than that of a large twig.

However, my programs, in particular the growing gargantuan that is the Blake Project wireless network base station and autonomous car coordinator, do get to do some cool stuff.

The coolest of these is using my computer's full capacity. There is a certain joy in writing a program that takes so long to run that you can have a cup of tea while it executes ... if you ignore the fact that it is only relatively recently that this has stopped being a common occurrence, and that most of the delay is due to your inefficiency anyway. The Blake Project base station is a prime example of this pride's initial warm glow swiftly followed by agonising pain of n-degree noob programming burns.

In order to service both a GUI and several external serial links the base station implements multi-threading, executing multiple scripts 'at once' (not really it just fills in all the empty space that usually fills up a single thread of execution). While it means I get to use fancy terms like 'concurrent processing' when describing system behaviour, all this filling of idle operations also means that the CPU utilisation can get fairly high as well.

Unfortunately it got slightly too high as seen below, and the program started to lag.
Multithreading in python is only able to use a single processor core. We can see it maxing out the leftmost core until I swiftly kill it.
The primary reason for this was that one of the older threads had been allowed to request access to shared resources a quickly as it liked. This is BAD news, because it can ask as often as it wants (or can - if we have to insist that computers are inanimate), not getting the resource shortens the time the thread does other stuff for before asking again because what it was going to to do relies on the resource being given to it. Think annoying 'are we there yet' questions which are incessant until the answer is 'yes'.

The spoilt child analogy naturally develops when the thread's response to actually getting the resource is to look at it, see that nothing has changed since last time it looked (the data it was looking for only came through every now and then), and thus immediatly close the resource and release it for others to use.

Only to immediately ask for it back.

The solution is to teach everyone some manners, introducing delays into the loops of which the loops are a part, and re-enabling 'blocking' of the requests (pausing the program until it is successful, which reduces the number of requests enormously - there were good reasons for me disabling this I promise). This is going to have knock on effects later on which may or may not be irrecoverable, luckily that is for future me to work out.

Threads with manners, now using the CPU cores in a much more respectable manner. I don't actually know which one it is running on!
In fact, there is a large chance that that is what my next post shall be about, we'll have to see!

No comments:

Post a Comment