Difference between revisions of "Python Multithreading/Multiprocessing Examples"

From dftwiki3
Jump to: navigation, search
(Example 1)
(Computing Pi, Serial Version)
Line 99: Line 99:
 
</source>
 
</source>
 
<br />
 
<br />
 +
==Computing Pi, Multithreaded Version==
 
<br />
 
<br />
 +
::<source lang="python">
 +
# ComputingPy.py
 +
# D. Thiebaut
 +
#
 +
# Computes an approximation of Pi by summing up
 +
# a series of terms.  The more terms, the closer
 +
# the approximation.
 +
#
 +
from __future__ import print_function
 +
import threading
 +
 +
 +
def f( x ):
 +
    """
 +
    The function being integrated, and which returns
 +
    an approximation of Pi when summed up over an interval
 +
    of integers.
 +
    """
 +
    return 4.0 / ( 1 + x*x )
 +
 +
class WorkerThread(threading.Thread):
 +
    """
 +
    That's the main worker thread, as a class.
 +
    It gets initialized via __init__ with the interval
 +
    and deltaX it sums up on.  It saves the accumulated
 +
    sum in self.sum
 +
    """
 +
   
 +
    def __init__( self, args ):
 +
        """
 +
        args must contain n1, n2, and deltaX, in that order.
 +
        """
 +
        threading.Thread.__init__( self, args=args )
 +
        self.n1 = args[0]
 +
        self.n2 = args[1]
 +
        self.deltaX = args[2]
 +
 +
    def run( self ):
 +
        """
 +
        This will be called automatically by start() in
 +
        main.  It's the method that does all the work.
 +
        """
 +
        self.sum = 0.0
 +
        for i in range( self.n1, self.n2 ):
 +
            self.sum += f( i * self.deltaX )
 +
 +
    def getSum( self ):
 +
        """
 +
        gets the computed sum.
 +
        """
 +
        return self.sum
 +
   
 +
def main():
 +
    """
 +
    Gets a number of terms from the user, then sums
 +
    up the series and prints the resulting sum, which
 +
    should approximate Pi.
 +
    """
 +
 +
    # get the number of terms
 +
    N = 1000000000 #int( input( "# steps > " ) )
 +
    T = 1000      #int( input( "# threads? > " ) )
 +
   
 +
    deltaX = 1.0 / N    # the interval
 +
    deltaN = int( N/T ) # the number of samples per thread
 +
 +
    # start T
 +
    n1 = 0
 +
    threads = []
 +
    for i in range( T ):
 +
        n2 = n1 + deltaN
 +
        t = WorkerThread( args=(n1, n2, deltaX,) )
 +
        t.start()
 +
        threads.append( t )
 +
        n1 = n2
 +
 +
    # wait for the threads to be done
 +
    for t in threads:
 +
        t.join()
 +
 +
    # gather the sums
 +
    sum = 0
 +
    for t in threads:
 +
        sum += t.getSum()
 +
 +
    # print result
 +
    print( "sum = %1.9f" % ( sum * deltaX ) )
 +
 +
main()
 +
       
 +
</source>
 
<br />
 
<br />
 
<br />
 
<br />

Revision as of 16:58, 25 January 2017

--D. Thiebaut (talk) 15:27, 25 January 2017 (EST)


Multithreading in Python


Warning! The multithreading module in Python does not provide true parallelism. Read up on the Global Interactive Lock if you want to learn more about this problem.

Example 1


# PythonThreading_Example1.py
# D. Thiebaut
# Taken and adapted from
# https://pymotw.com/2/threading/
#
# Python program illustrating how threads can
# be created and started in Python

from __future__ import print_function
import threading
import time


def worker( Id ):
    """
    thread worker function.  It receives an Id,
    and prints a message indicating it's starting.
    waits 0.5 seconds, prints another message, and dies.
    """
    print( 'Worker %d started\n' % Id )
    time.sleep( 0.5 )
    print( 'Worker %d finished\n' % Id )
    return

def main():
    """
    Spawns 5 threads that will run the worker function.
    Waits for the threads to finish, then stops.
    """
    threads = []
    for i in range(5):
        t = threading.Thread( target=worker, args=(i,) )
        threads.append(t)
        t.start()
    print( "Main has spawn all the threads" )

    # wait for all the threads to finish
    for t in threads:
        t.join()
        
    print( "Done!" )
    
main()


Computing Pi, Serial Version


# ComputingPy.py
# D. Thiebaut
#
# Computes an approximation of Pi by summing up
# a series of terms.  The more terms, the closer
# the approximation.
#

def f( x ):
    """
    The function being integrated, and which returns
    an approximation of Pi when summed up over an interval
    of integers.
    """
    return 4.0 / ( 1 + x*x )


def main():
    """
    Gets a number of terms from the user, then sums
    up the series and prints the resulting sum, which
    should approximate Pi.
    """

    # get the number of terms
    N = int( input( "> " ) )

    sum = 0.0          # where we sum up the individual
                       # intervals
    deltaX = 1.0 / N   # the interval

    # sum over N terms
    for i in range( N ):
        sum += f( i * deltaX )

    # display results
    print( "sum = %1.9f" % ( sum * deltaX ) )

main()


Computing Pi, Multithreaded Version


# ComputingPy.py
# D. Thiebaut
#
# Computes an approximation of Pi by summing up
# a series of terms.  The more terms, the closer
# the approximation.
#
from __future__ import print_function
import threading


def f( x ):
    """
    The function being integrated, and which returns
    an approximation of Pi when summed up over an interval
    of integers.
    """
    return 4.0 / ( 1 + x*x )

class WorkerThread(threading.Thread):
    """
    That's the main worker thread, as a class.
    It gets initialized via __init__ with the interval
    and deltaX it sums up on.  It saves the accumulated
    sum in self.sum
    """
    
    def __init__( self, args ):
        """
        args must contain n1, n2, and deltaX, in that order.
        """
        threading.Thread.__init__( self, args=args )
        self.n1 = args[0]
        self.n2 = args[1]
        self.deltaX = args[2]

    def run( self ):
        """
        This will be called automatically by start() in
        main.  It's the method that does all the work.
        """
        self.sum = 0.0
        for i in range( self.n1, self.n2 ):
            self.sum += f( i * self.deltaX )

    def getSum( self ):
        """
        gets the computed sum.
        """
        return self.sum
    
def main():
    """
    Gets a number of terms from the user, then sums
    up the series and prints the resulting sum, which
    should approximate Pi.
    """

    # get the number of terms
    N = 1000000000 #int( input( "# steps > " ) )
    T = 1000       #int( input( "# threads? > " ) )
    
    deltaX = 1.0 / N    # the interval
    deltaN = int( N/T ) # the number of samples per thread

    # start T 
    n1 = 0
    threads = []
    for i in range( T ):
        n2 = n1 + deltaN
        t = WorkerThread( args=(n1, n2, deltaX,) )
        t.start()
        threads.append( t )
        n1 = n2

    # wait for the threads to be done
    for t in threads:
        t.join()

    # gather the sums
    sum = 0
    for t in threads:
        sum += t.getSum()

    # print result
    print( "sum = %1.9f" % ( sum * deltaX ) )

main()