{ "cells": [ { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "# Function chaining\n", "\n", "Function chaining is a pattern where multiple functions are called on the same executor consecutively. Using the\n", "same `lithops.FunctionExecutor` object reference, multiple functions can be invoked. It increases the readability of the\n", "code and means less redundancy. This means we chain multiple functions together with the same element reference. It’s\n", "not necessary to attach the `lithops.FunctionExecutor` reference multiple times for each function call.\n", "\n", "This patter is specially useful when the output of one invocation is the input of another invocation. In this case,\n", "Lithops does not download the intermediate results to the local client, instead, the intermediate results are directly\n", "read from the next function.\n", "\n", "It currently works with the Futures API, and you can chain the `map()`, `map_reuce()`, `wait()` and `get_result()`\n", "methods. Note that the returning value of one function must match the signature of the next function when chaining\n", "multiple `map()` calls. View the next examples:\n", "\n", "Getting the result from a single `map()` call:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2, 4, 6]\n" ] } ], "source": [ "import lithops\n", "\n", "\n", "def my_func1(x):\n", " return x * 2\n", "\n", "\n", "iterdata = [1, 2, 3]\n", "\n", "fexec = lithops.FunctionExecutor()\n", "res = fexec.map(my_func1, iterdata).get_result()\n", "print(res)" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "Chain multiple `map()` calls and get the final result:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[7, 9, 11]\n" ] } ], "source": [ "import lithops\n", "\n", "\n", "def my_func1(x):\n", " return x * 2, 5\n", "\n", "\n", "def my_func2(x, y):\n", " return x + y\n", "\n", "\n", "iterdata = [1, 2, 3]\n", "\n", "fexec = lithops.FunctionExecutor()\n", "res = fexec.map(my_func1, iterdata).map(my_func2).get_result()\n", "print(res)" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "There is no limit in the number of `map()` calls that can be chained:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[15, 16, 17]\n" ] } ], "source": [ "def my_func1(x):\n", " return x + 2, 5\n", "\n", "\n", "def my_func2(x, y):\n", " return x + y, 5, 2\n", "\n", "\n", "def my_func3(x, y, z):\n", " return x + y + z\n", "\n", "\n", "iterdata = [1, 2, 3]\n", "\n", "fexec = lithops.FunctionExecutor()\n", "res = fexec.map(my_func1, iterdata).map(my_func2).map(my_func3).get_result()\n", "print(res)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, you can pass the `futures` generated in a `map()` or `map_reduce()` call to the `iterdata` parameter with\n", "the same effect. Not that in this case you will only get the results of the last `map()` execution. Results of\n", "intermediate `map()`s are never downloaded:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[15, 16, 17]\n" ] } ], "source": [ "def my_func1(x):\n", " return x + 2, 5\n", "\n", "\n", "def my_func2(x, y):\n", " return x + y, 5, 2\n", "\n", "\n", "def my_func3(x, y, z):\n", " return x + y + z\n", "\n", "\n", "iterdata = [1, 2, 3]\n", "\n", "fexec = lithops.FunctionExecutor()\n", "futures1 = fexec.map(my_func1, iterdata)\n", "futures2 = fexec.map(my_func2, futures1)\n", "futures3 = fexec.map(my_func3, futures2)\n", "final_result = fexec.get_result()\n", "\n", "print(final_result)\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.10" } }, "nbformat": 4, "nbformat_minor": 4 }