Page 1 of 1

Thread vs Multiprocessor on RPi model b

Posted: Sat Sep 16, 2017 3:32 pm
by Craigjw
I have a raspberry pi model B and using Python 3 to program an application

Is there any benefit to using multiprocessing over threads on this board, as the processor is single core, I can't see that there would be any advantage as either would be processed serially.

I'm currently using threads, which I know aren't processed parallel and would like to know if it's worth switching over to multiprocessor commands for processing the code instead of threads.

Thanks in advance.

Re: Thread vs Multiprocessor on RPi model b

Posted: Sat Sep 16, 2017 3:49 pm
by W. H. Heydt
When there are multiple cores (and if you only have a single core you're using a very old Pi, or an A+, Pi0, or Pi0W), how processes are scheduled onto the core is handled by the operating system. Multitasking--whether on a single core or multiple cores--is done using time slice algorithms. Of course, if a given process is waiting on I/O, it won't get a time slice. Since many sorts of processes are I/O bound, *most* of the time you don't see things being slowed down because of the multitasking.

Re: Thread vs Multiprocessor on RPi model b

Posted: Sat Sep 16, 2017 4:26 pm
by Heater
Craigjw,
Is there any benefit to using multiprocessing over threads on this board, as the processor is single core, I can't see that there would be any advantage as either would be processed serially.
Let's assume that we only want multiple cores so that we can run multiple threads at the same time and get better performance.

Then why do we need threads at all?

Let's say that in my Python code I want to flash a LED. I might have a loop like this:

Code: Select all

def blink():
  while True:
    GPIO.output(LedPin, GPIO.HIGH)  # led on
    time.sleep(1)
    GPIO.output(LedPin, GPIO.LOW) # led off
    time.sleep(1)
Then let's say I wanted to get some user input from the keyboard, to change the flash rate for example, that requires a loop like this:

Code: Select all

def userInput():
  while True:
    name = input("Command? ")
    # Do something with user input
Oops... that does not work. When "input" is waiting there is no way to run the blink loop. When "sleep" is sleeping there is no way to read the user input.

What to do?

Oh yes, introduce threads, so that both of those loops can run at the same time.

Code: Select all

import thread
import time

# Define a function for the LED flashing thread
def blink():
  while True:
    GPIO.output(LedPin, GPIO.HIGH)  # led on
    time.sleep(1)
    GPIO.output(LedPin, GPIO.LOW) # led off
    time.sleep(1)

# Define a function for the LED flashing thread
def userInput():
  while True:
    name = input("Command? ")
    # Do something with user input

# Create two threads as follows
try:
   thread.start_new_thread( blink, ("Thread-1", 2, ) )
   thread.start_new_thread( userInput, ("Thread-2", 4, ) )
except:
   print "Error: unable to start thread"

while 1:
   pass
Great, now my LED flashes at the same time the LED blinks. (Sorry if that code is not totally correct. I'm no Python user.)

Now, as W.H.Heydt says, these threads are ultimately juggled around by the Linux kernel. It does not matter if there is one core or many. The program will look the same. Unless you really need performance that is.

Of course this threading business is silly. There is a lot of complexity, inefficiency and overhead in there.

For example in Javascript under node.js the same could be done with something like this:

Code: Select all

var ledState = 0;
setInterval (function () {
  gpio.write(pinNumber, ledState)
  ledState = (ledState + 1) % 2
}, 1000)

var stdio = require('stdio');
    stdio.question('Command?', function (err, input) {
      // Do whatever you want with "input"
});
Which I think you might agree is much shorter and nicer.

Re: Thread vs Multiprocessor on RPi model b

Posted: Sat Sep 16, 2017 4:39 pm
by mikerr
On a single core model B (or zero) - not much performance difference, in fact processes have more overhead, so may be slower.

but a multithreaded python program doesn't get any quicker on a multicore cpu - all threads one one core
whereas multiprocessing takes advantage of extra cores when available.

Something to consider if you move the program over to a multicore pi3 at some point.

Re: Thread vs Multiprocessor on RPi model b

Posted: Sat Sep 16, 2017 4:45 pm
by mattmiller
Is there any benefit to using multiprocessing over threads on this board, as the processor is single core, I can't see that there would be any advantage as either would be processed serially.
Assuming Python, multiprocessing is just a different way of implementing multi-tasking - the "processor" bit is different concept from number of cpu cores.

it depends on what exact tasks your trying to do at the same time if one method is faster than the other

I believe its generally not worth worrying about unless doing some highly specific tasks might benefit from multiprocessing over threading

Re: Thread vs Multiprocessor on RPi model b

Posted: Sat Sep 16, 2017 4:54 pm
by Heater
mikerr,
but a multithreaded python program doesn't get any quicker on a multicore cpu - all threads one one core
What? Python is even more brain damaged than I thought.

Ah, looks like you have to use the Process module. Something like:

Code: Select all

from multiprocessing import Process
import time

# Define a function for the LED flashing process
def blink():
  while True:
    GPIO.output(LedPin, GPIO.HIGH)  # led on
    time.sleep(1)
    GPIO.output(LedPin, GPIO.LOW) # led off
    time.sleep(1)

# Define a function for the LED flashing process
def userInput():
  while True:
    name = input("Command? ")
    # Do something with user input

# Create two processes as follows
try:
  p1 = Process(target=blink)
  p1.start()
  p1 = Process(target=userInput)
  p1.start()
except:
   print "Error: unable to start process"

p1.join()
p2.join()
Although God knows what happens when you want to share data between those processes...

Re: Thread vs Multiprocessor on RPi model b

Posted: Sat Sep 16, 2017 7:59 pm
by OutoftheBOTS
This is my experience with multiprocessing.

It is very tricky because you can be parallel computing and it is possible for 2 processes running 2 diffent cores to try to write to the same shared memerory at the saem time causing corruption of the data in the memory.

Also as mentioned above the OS handles a lot of what is going on and quite often the OS at a lower level can already be running different processes on different cores already.

Most of all what I have found is if your doing something that complex that would require multiprocessing and your using a prebuilt library that was written in a low level language like C then compiled to an API chances r it has already been optimized to use multiprocessing. One example is using Numpy arrays, if your doing vector multiplication with Numpy arrays you will find that at a lower level it has been highly optimized for parallel multiprocessing and if you try to speed things up by using multiprocessing you in fact slow it down. Try timing your program to complete tasks then do the same task in a different way (multiprocessing) and time it again and see the differeence.

Re: Thread vs Multiprocessor on RPi model b

Posted: Sat Sep 16, 2017 9:24 pm
by W. H. Heydt
OutoftheBOTS wrote:
Sat Sep 16, 2017 7:59 pm
This is my experience with multiprocessing.

It is very tricky because you can be parallel computing and it is possible for 2 processes running 2 diffent cores to try to write to the same shared memerory at the saem time causing corruption of the data in the memory.
That's why multiprocessor designs include special machine instructions to prevent that sort of problem...and have since the days of SMP mainframes. (Not to pick on you in particular, but it's pretty amazing that microprocessor people seem to think that every innovation they come up with is something new and unprecedented, rather than being something that mainframes did to solve the same problem 50 years earlier.)

What I find implied in this this whole issue of how threading is handled is how reminiscent it is of CICS on mainframes 40-odd years ago. While running on an intrinsically multitasking system (whether or not it is also multiprocessing), you have a local "monitor" (CICS then, Python now) that insists on doing its own task management instead of letting the OS do it globally. Now to be fair, CICS did originate on single tasking systems, so you can see why task management was incorporated into it and wasn't removed when the OSes gained multitaking features. But what is Pythons excuse for doing the same thing post-multitaking OSes?