Parallel Processing in Ruby using fork

pradeep's Avatar author of Parallel Processing in Ruby using fork
This is an article on Parallel Processing in Ruby using fork in Programming.
In today's multitasking and multiprocessing environment it sometimes becomes necessary for programs to run certain tasks in parallel to be fast. Fork-ing provides just that. Fork is a system call which creates a clone of the process which first calls fork() and is called the parent process and the cloned process the child process, the return value of fork call helps each process determine whether they are a parent or a child. A more efficient solution to parallel processing are threads, but they need careful planning to be implemented as desired, but forking is easier to implement with a little more efficiency overhead than threads.

In this Ruby article we'll be looking a creating child processes in Ruby and implementing simple parallel tasks with it, waiting for all child processes to finish and also checking exit status of the child processes.

Forking in Ruby



A code snippet says a lot more than words, so let's see a very simple snippet where we fork a child and print time:

Code: Ruby
# create the child process
pid = fork {
    ## loop 3 times
    3.times do
        p Time.now.to_s
        sleep(1)
    end
}

Output:

Code:
[pradeep@home-desktop ~]$ ./fork.rb
"2014-04-22 06:02:21 -0700"
[pradeep@home-desktop ~]$ "2014-04-22 06:02:22 -0700"
"2014-04-22 06:02:23 -0700"

[pradeep@home-desktop ~]$

As you can see the parent process exited and the child process kept on printing the output, so the parent process does not know if the child process finished execution successfully or not. In the next code snippet we will make the parent wait for all child processes to finish and print their exit status.

Code: Ruby
## exit code 0 means success, everything else means failure
exit_codes = Array(0..4)

exit_codes.each { |exit_code|
    pid = fork {
        sleep(2)
        p Time.now.to_s
        ## specify exit status code
        exit(exit_code)
    }

    p "Created child process - #{pid}"
}

## wait for all child processes to finish
while true
    p "waiting for child processes"
    begin
        exited_pid = Process.waitpid(0,Process::WNOHANG)
        if exited_pid and exited_pid > 0 then
            p "Process exited : #{exited_pid} with status #{$?.exitstatus }"
        end
        sleep(1)
    rescue SystemCallError
        p "No more child processes to wait for exiting parent"
        break
    end
end

Output:

Code:
[pradeep@home-desktop ~]$ ./fork.rb
"Created child process - 14238"
"Created child process - 14241"
"Created child process - 14244"
"Created child process - 14247"
"Created child process - 14250"
"waiting for child processes"
"waiting for child processes"
"2014-04-22 06:15:34 -0700"
"2014-04-22 06:15:34 -0700"
"2014-04-22 06:15:34 -0700"
"2014-04-22 06:15:34 -0700"
"waiting for child processes"
"Process exited : 14238 with status 0"
"2014-04-22 06:15:34 -0700"
"waiting for child processes"
"Process exited : 14241 with status 1"
"waiting for child processes"
"Process exited : 14244 with status 2"
"waiting for child processes"
"Process exited : 14247 with status 3"
"waiting for child processes"
"Process exited : 14250 with status 4"
"waiting for child processes"
"No more child processes to wait for exiting parent"
These codes were very basic, you can use this basic knowledge to create scripts to get you simple or complex work done. Do post your feedback/queries/suggestions.
shabbir like this