-
Notifications
You must be signed in to change notification settings - Fork 8
BigJob Tutorial Part 4: Mandelbrot Example
This page is part of the BigJob Tutorial.
In this example, we split up the calculation of a Mandelbrot set into several tiles.
Rather than submit a single job for each tile, we want to submit one BigJob and then execute each individual tile job in a distributed fashion. This is why BigJob is useful. We reserve the resources we need for all of the jobs, but submit just one job that requests all of these resources. Once the job becomes active, the compute units are executed in a distributed fashion. The tiles are then retrieved using features included in BigJob such as the SAGA File API, and the final image is stitched together from the individual tiles.
In order for this example to work, we need to install an additional Python module, the Python Image Library (PIL). This is done via pip:
pip install PIL
Next, we need to download the Mandelbrot fractal generator itself. It is really just a very simple python script that, if invoked on the command line, outputs a full or part of a Mandelbrot fractal as a PNG image. Download the script into your $HOME
directory:
curl --insecure -Os https://raw.github.com/saga-project/bliss/master/examples/advanced/mandelbrot/mandelbrot.py
You can give mandelbrot.py a test-drive locally by calculating a single-tiled 1024x1024 Mandelbrot fractal:
python mandelbrot.py 1024 1024 0 1024 0 1024 frac.gif
Cut and paste code below into bj_mandelbrot.py
.
import os, time, sys
from PIL import Image
import bliss.saga as saga
from pilot import PilotComputeService, ComputeDataService, State
# the dimension (in pixel) of the whole fractal
imgx = 8192
imgy = 8192
# the number of tiles in X and Y direction
tilesx = 2
tilesy = 2
### This is the number of jobs you want to run
NUMBER_JOBS=4
COORDINATION_URL = "redis://localhost"
if __name__ == "__main__":
pilot_compute_service = PilotComputeService(COORDINATION_URL)
# copy image tiles back to our 'local' directory
dirname = 'sftp://localhost/%s/PJ-mbrot/' % '/tmp'
workdir = saga.filesystem.Directory(dirname, saga.filesystem.Create)
pilot_compute_description={ "service_url": "fork://localhost",
"number_of_processes": 12,
#"allocation": "XSEDE12-SAGA",
#"queue": "development",
"working_directory": workdir.get_url().path,
"walltime":10
}
pilot_compute_service.create_pilot(pilot_compute_description=pilot_compute_description)
compute_data_service = ComputeDataService()
compute_data_service.add_pilot_compute_service(pilot_compute_service)
print ("Finished Pilot-Job setup. Submitting compute units")
# submit compute units
for x in range(0, tilesx):
for y in range(0, tilesy):
# describe a single Mandelbrot job. we're using the
# directory created above as the job's working directory
outputfile = 'tile_x%s_y%s.gif' % (x,y)
compute_unit_description = {
"executable": "python",
"arguments": [os.getenv("HOME")+'/mandelbrot.py', str(imgx), str(imgy),
str(imgx/tilesx*x), str(imgx/tilesx*(x+1)),
str(imgy/tilesy*y), str(imgy/tilesy*(y+1)),
outputfile],
"number_of_processes": 1,
"working_directory":workdir.get_url().path,
"output": "stdout_x%s_y%s.txt" % (x,y),
"error": "stderr_x%s_y%s.txt" % (x,y),
}
compute_data_service.submit_compute_unit(compute_unit_description)
print ("Waiting for compute units to complete")
compute_data_service.wait()
# Preparing the final image
for image in workdir.list('*.gif'):
print ' * Copying %s/%s back to %s' % (workdir.get_url(), image, os.getcwd())
workdir.copy(image, 'sftp://localhost/%s/' % os.getcwd())
# stitch together the final image
fullimage = Image.new('RGB',(imgx, imgy),(255,255,255))
print ' * Stitching together the whole fractal: mandelbrot_full.png'
for x in range(0, tilesx):
for y in range(0, tilesy):
partimage = Image.open('tile_x%s_y%s.gif' % (x, y))
fullimage.paste(partimage, (imgx/tilesx*x, imgy/tilesy*y, imgx/tilesx*(x+1), imgy/tilesy*(y+1)) )
fullimage.save("mandelbrot_full.gif", "GIF")
print ("Terminate Pilot Jobs")
compute_data_service.cancel()
pilot_compute_service.cancel()
Execute the bj_mandelbrot.py script using command
python bj_mandelbrot.py
Compare the execution of bj_mandelbrot.py to its SAGA counterpart saga_mandelbrot.py. Notice that a pilot-job is used in the BigJob case to submit many jobs at one time, instead of submitting them serially as in the SAGA example.
Back: [Tutorial Home](BigJob Tutorial) Next: BigJob Tutorial Part 5: Chained Ensemble Example