Parallel Processing in Ruby using fork

Discussion in 'Programming' started by pradeep, Apr 22, 2014.

  1. pradeep

    pradeep Team Leader

    Joined:
    Apr 4, 2005
    Messages:
    1,645
    Likes Received:
    87
    Trophy Points:
    0
    Occupation:
    Programmer
    Location:
    Kolkata, India
    Home Page:
    http://blog.pradeep.net.in
    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:
    # 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:
    ## 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 likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice