You might be coming from Python, right? ;-)
It has the module named
multiprocessing
in its stdlib, and this might well explain why you have used
this name in the title of your question and why you apparently
are having trouble interpreting what @JimB meant by saying
If you need a separate process, you need to exec it yourself
"Multiprocessing" in Python
The thing is, Python's multiprocessing is a quite high-level
thing which hides under its hood a whole lot of stuff.
When you spawn a multiprocessing.Process and make it run
a function, what really happens is this:
The Python interpreter creates another operating system's process (using
fork(2)on Unix-like systems orCreateProcesson Windows) and arranges for it to execute a Python interpter, too.The crucial point is that you will now have two processes running two Python interpters.
It is arranged for that Python interpterer in the child process to have a way to communicate with the Python interpreter in the parent process.
This "communication link" necessarily involves some form of IPC @JimB referred to. There is simply no other way to communicate data and actions between separate processes exactly because a commodity contemporary OS provides strict process separation.
When you exchange Python objects between the processes, the two communicating Python interpreters serialize and deserialize them behind your back before sending them over their IPC link and after receiving them from there, correspondingly. This is implemented using the
picklemodule.
Back to Go
Go does not have any direct solution which would closely
match Python's multiprocessing, and I really doubt it could
have been sensibly implemented.
The chief reason for this mostly stems from the fact Go is quite more lower level than Python, and hence it does not have the Python's luxury of making sheer assumptions about the types of values it manages, and it also strives to have as few hidden costs in its constructs as possible.
Go also strives to steer clear of "framework-style" approaches
to solve problems, and use "library-style" solutions when
possible. (A good rundown of the "framework vs library"
is given, for instance, here.)
Go has everything in its standard library to implement
something akin to Python's multiprocessing but there is no
ready-made frakework-y solution for this.
So what you could do for this is to roll along these lines:
Use
os/execto run another copy of your own process.- Make sure the spawned process "knows" it's started in the special "slave" mode—to act accordingly.
- Use any form of IPC to communicate with the new process. Exchanging data via the standard I/O streams of the child process is supposedly the simplest way to roll (except when you need to exchange opened files but this is a harder topic, so let's not digress).
Use any suitable package in the
encoding/hierarchy — such asbinary,gob,xml— to serialize and deserialize data when exchanging.The "go-to" solution is supposedly
encoding/gobbutencoding/jsonwill also do just fine.Invent and implement a simple protocol to tell the child process what to do, and with which data, and how to communicate the results back to master.
Does it really worth the trouble?
I would say that no, it doesn't—for a number of reasons:
Go has nothing like the dreaded GIL, so there's no need to sidestep it to achieve real parallelism when it is naturally possible.
Memory safety is all in your hands, and achieving it is not really that hard when you dutifully obey the principle that what is sent over a channel is now owned by the receiver. In other words, sending values over a channel is also the transfer of ownership of those values.
The Go toolchain has integrated race detector, so you may run your test suite with the
-raceflag and create evaluation builds of your program usinggo build -racefor the same purpose: when a program instrumented in such a way runs, the race detector crashes it as soon as it detects any unsynchronized read/write memory access. The printout resulting from that crash includes explanatory messages on what, and where went wrong, with stack traces.IPC is slow, so the gains may well be offset by the losses.
All-in-all, I see no real reason to separate processes unless you're writing something like an e-mail processing server where this concept comes naturally.
Answer from kostix on Stack OverflowYou might be coming from Python, right? ;-)
It has the module named
multiprocessing
in its stdlib, and this might well explain why you have used
this name in the title of your question and why you apparently
are having trouble interpreting what @JimB meant by saying
If you need a separate process, you need to exec it yourself
"Multiprocessing" in Python
The thing is, Python's multiprocessing is a quite high-level
thing which hides under its hood a whole lot of stuff.
When you spawn a multiprocessing.Process and make it run
a function, what really happens is this:
The Python interpreter creates another operating system's process (using
fork(2)on Unix-like systems orCreateProcesson Windows) and arranges for it to execute a Python interpter, too.The crucial point is that you will now have two processes running two Python interpters.
It is arranged for that Python interpterer in the child process to have a way to communicate with the Python interpreter in the parent process.
This "communication link" necessarily involves some form of IPC @JimB referred to. There is simply no other way to communicate data and actions between separate processes exactly because a commodity contemporary OS provides strict process separation.
When you exchange Python objects between the processes, the two communicating Python interpreters serialize and deserialize them behind your back before sending them over their IPC link and after receiving them from there, correspondingly. This is implemented using the
picklemodule.
Back to Go
Go does not have any direct solution which would closely
match Python's multiprocessing, and I really doubt it could
have been sensibly implemented.
The chief reason for this mostly stems from the fact Go is quite more lower level than Python, and hence it does not have the Python's luxury of making sheer assumptions about the types of values it manages, and it also strives to have as few hidden costs in its constructs as possible.
Go also strives to steer clear of "framework-style" approaches
to solve problems, and use "library-style" solutions when
possible. (A good rundown of the "framework vs library"
is given, for instance, here.)
Go has everything in its standard library to implement
something akin to Python's multiprocessing but there is no
ready-made frakework-y solution for this.
So what you could do for this is to roll along these lines:
Use
os/execto run another copy of your own process.- Make sure the spawned process "knows" it's started in the special "slave" mode—to act accordingly.
- Use any form of IPC to communicate with the new process. Exchanging data via the standard I/O streams of the child process is supposedly the simplest way to roll (except when you need to exchange opened files but this is a harder topic, so let's not digress).
Use any suitable package in the
encoding/hierarchy — such asbinary,gob,xml— to serialize and deserialize data when exchanging.The "go-to" solution is supposedly
encoding/gobbutencoding/jsonwill also do just fine.Invent and implement a simple protocol to tell the child process what to do, and with which data, and how to communicate the results back to master.
Does it really worth the trouble?
I would say that no, it doesn't—for a number of reasons:
Go has nothing like the dreaded GIL, so there's no need to sidestep it to achieve real parallelism when it is naturally possible.
Memory safety is all in your hands, and achieving it is not really that hard when you dutifully obey the principle that what is sent over a channel is now owned by the receiver. In other words, sending values over a channel is also the transfer of ownership of those values.
The Go toolchain has integrated race detector, so you may run your test suite with the
-raceflag and create evaluation builds of your program usinggo build -racefor the same purpose: when a program instrumented in such a way runs, the race detector crashes it as soon as it detects any unsynchronized read/write memory access. The printout resulting from that crash includes explanatory messages on what, and where went wrong, with stack traces.IPC is slow, so the gains may well be offset by the losses.
All-in-all, I see no real reason to separate processes unless you're writing something like an e-mail processing server where this concept comes naturally.
Channel is used for communicating between goroutines, you shouldn't use it in same goroutine like this code:
sensorData <- string(msg.Payload())
fmt.Println(<-sensorData) //currently not printing anything
If you like to test printing by channel, you can use buffered channel in same goroutine to avoid blocking, like this:
sensorData := make(chan []byte, 1)
Cheers
How does Golang handle concurrency and parallelism differently?
How do goroutines improve performance in Golang applications?
Why are goroutines better than traditional multithreading?
This is more of a computer science question, but for a program that has no blocking operations (e.g. file or network IO), and just needs to churn through some data, is it worth parallelising this? If the work needs to be done either way, does adding Goroutines make it any faster?
Sorry if this is a silly question, I've always seen multithreading as a way to handle totally different lines of execution, rather than just approaching the same line of execution with multiple threads.
In Python, a common way to improve throughput is to start multiple processes on the same machine. Think Tornado + supervisord + nginx.
Nginx acts as a loadbalancer between the multiple processes spawned by supervisord. This is useful because Python is single threaded and this helps being in "true" concurrency from multiple processes.
Does a similar setup help with Golang?