From adf417cda526f4551079a0ae3fdcdeb8b803be09 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Thu, 10 Jul 2014 17:23:42 -0700 Subject: [PATCH] Add a mandelbrot parallel calculation WBE example The mandelbrot calculation is neat example to provide to show how the WBE engine can be used to compute various calculations (the mandelbrot set in this example). This will also create an image from the output if a filename is provided and the pillow library is installed (that library does the actual image writing). See: http://en.wikipedia.org/wiki/Mandelbrot_set Part of blueprint more-examples Change-Id: I12b9b7a2ce61b17ddaa2930cc9cf266ae0c60932 --- doc/source/examples.rst | 23 ++ doc/source/img/mandelbrot.png | Bin 0 -> 21971 bytes taskflow/examples/wbe_mandelbrot.out.txt | 6 + taskflow/examples/wbe_mandelbrot.py | 254 +++++++++++++++++++++++ 4 files changed, 283 insertions(+) create mode 100644 doc/source/img/mandelbrot.png create mode 100644 taskflow/examples/wbe_mandelbrot.out.txt create mode 100644 taskflow/examples/wbe_mandelbrot.py diff --git a/doc/source/examples.rst b/doc/source/examples.rst index 9199bc11b..a6f0dd9fd 100644 --- a/doc/source/examples.rst +++ b/doc/source/examples.rst @@ -163,3 +163,26 @@ Distributed execution (simple) :language: python :linenos: :lines: 16- + +Distributed mandelbrot (complex) +================================ + +.. note:: + + Full source located at :example:`wbe_mandelbrot` + +Output +------ + +.. image:: img/mandelbrot.png + :height: 128px + :align: right + :alt: Generated mandelbrot fractal + +Code +---- + +.. literalinclude:: ../../taskflow/examples/wbe_mandelbrot.py + :language: python + :linenos: + :lines: 16- diff --git a/doc/source/img/mandelbrot.png b/doc/source/img/mandelbrot.png new file mode 100644 index 0000000000000000000000000000000000000000..6dc26ee5e617d423977ab25d9fe70e68b8aee5d2 GIT binary patch literal 21971 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 O0000= 4: + return i + return max_iters + + min_x, max_x, min_y, max_y, max_iters = mandelbrot_config + height, width = image_config['size'] + pixel_size_x = (max_x - min_x) / width + pixel_size_y = (max_y - min_y) / height + block = [] + for y in six.moves.xrange(chunk[0], chunk[1]): + row = [] + imag = min_y + y * pixel_size_y + for x in six.moves.xrange(0, width): + real = min_x + x * pixel_size_x + row.append(mandelbrot(real, imag, max_iters)) + block.append(row) + return block + + +def calculate(engine_conf): + # Subdivide the work into X pieces, then request each worker to calculate + # one of those chunks and then later we will write these chunks out to + # an image bitmap file. + + # And unordered flow is used here since the mandelbrot calculation is an + # example of a embarrassingly parallel computation that we can scatter + # across as many workers as possible. + flow = uf.Flow("mandelbrot") + + # These symbols will be automatically given to tasks as input to there + # execute method, in this case these are constants used in the mandelbrot + # calculation. + store = { + 'mandelbrot_config': [-2.0, 1.0, -1.0, 1.0, MAX_ITERATIONS], + 'image_config': { + 'size': IMAGE_SIZE, + } + } + + # We need the task names to be in the right order so that we can extract + # the final results in the right order (we don't care about the order when + # executing). + task_names = [] + + # Compose our workflow. + height, width = IMAGE_SIZE + chunk_size = int(math.ceil(height / float(CHUNK_COUNT))) + for i in six.moves.xrange(0, CHUNK_COUNT): + chunk_name = 'chunk_%s' % i + task_name = "calculation_%s" % i + # Break the calculation up into chunk size pieces. + rows = [i * chunk_size, i * chunk_size + chunk_size] + flow.add( + MandelCalculator(task_name, + # This ensures the storage symbol with name + # 'chunk_name' is sent into the tasks local + # symbol 'chunk'. This is how we give each + # calculator its own correct sequence of rows + # to work on. + rebind={'chunk': chunk_name})) + store[chunk_name] = rows + task_names.append(task_name) + + # Now execute it. + eng = engines.load(flow, store=store, engine_conf=engine_conf) + eng.run() + + # Gather all the results and order them for further processing. + gather = [] + for name in task_names: + gather.extend(eng.storage.get(name)) + points = [] + for y, row in enumerate(gather): + for x, color in enumerate(row): + points.append(((x, y), color)) + return points + + +def write_image(results, output_filename=None): + print("Gathered %s results that represents a mandelbrot" + " image (using %s chunks that are computed jointly" + " by %s workers)." % (len(results), CHUNK_COUNT, WORKERS)) + if not output_filename: + return + + # Pillow (the PIL fork) saves us from writing our own image writer... + try: + from PIL import Image + except ImportError as e: + # To currently get this (may change in the future), + # $ pip install Pillow + raise RuntimeError("Pillow is required to write image files: %s" % e) + + # Limit to 255, find the max and normalize to that... + color_max = 0 + for _point, color in results: + color_max = max(color, color_max) + + # Use gray scale since we don't really have other colors. + img = Image.new('L', IMAGE_SIZE, "black") + pixels = img.load() + for (x, y), color in results: + if color_max == 0: + color = 0 + else: + color = int((float(color) / color_max) * 255.0) + pixels[x, y] = color + img.save(output_filename) + + +def create_fractal(): + logging.basicConfig(level=logging.ERROR) + + # Setup our transport configuration and merge it into the worker and + # engine configuration so that both of those use it correctly. + shared_conf = dict(BASE_SHARED_CONF) + shared_conf.update({ + 'transport': 'memory', + 'transport_options': { + 'polling_interval': 0.1, + }, + }) + + if len(sys.argv) >= 2: + output_filename = sys.argv[1] + else: + output_filename = None + + worker_conf = dict(WORKER_CONF) + worker_conf.update(shared_conf) + engine_conf = dict(ENGINE_CONF) + engine_conf.update(shared_conf) + workers = [] + worker_topics = [] + + print('Calculating your mandelbrot fractal of size %sx%s.' % IMAGE_SIZE) + try: + # Create a set of workers to simulate actual remote workers. + print('Running %s workers.' % (WORKERS)) + for i in range(0, WORKERS): + worker_conf['topic'] = 'calculator_%s' % (i + 1) + worker_topics.append(worker_conf['topic']) + w = worker.Worker(**worker_conf) + runner = threading.Thread(target=w.run) + runner.daemon = True + runner.start() + w.wait() + workers.append((runner, w.stop)) + + # Now use those workers to do something. + engine_conf['topics'] = worker_topics + results = calculate(engine_conf) + print('Execution finished.') + finally: + # And cleanup. + print('Stopping workers.') + while workers: + r, stopper = workers.pop() + stopper() + r.join() + print("Writing image...") + write_image(results, output_filename=output_filename) + + +if __name__ == "__main__": + create_fractal()