{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Parallel Programming Example" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Python version" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def mandel(x, y, max_iters):\n", " c = complex(x, y)\n", " z = 0.0j\n", " for i in range(max_iters):\n", " z = z*z + c\n", " if abs(z) >= 4:\n", " return i\n", " return max_iters\n", "\n", "def create_fractal(xmin, xmax, ymin, ymax, image, iters):\n", " height, width = image.shape\n", "\n", " pixel_size_x = (xmax - xmin)/width\n", " pixel_size_y = (ymax - ymin)/height\n", "\n", " for x in range(width):\n", " real = xmin + x*pixel_size_x\n", " for y in range(height):\n", " imag = ymin + y*pixel_size_y\n", " color = mandel(real, imag, iters)\n", " image[y, x] = color" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that we use a 16-fold smaller image for the Python version." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 3.07 s, sys: 0 ns, total: 3.07 s\n", "Wall time: 3.1 s\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXEAAAD8CAYAAACB3pQWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAAIABJREFUeJzsvX1wFOed7/t5xGbti7iODBJS/CLMBRH5IBdikUVuZffMgAlafLdiDJIHuHVOckwwCKhKjlm/4NhRK05sxxxIcgsQmAO12VsHkHmxkzoVHbFgRneTcxZZDrAWaxZBCLJxJCQZhZVc9m7Qc/94umd6enpeNS89o/5UTc1bT/cz0z3f/vXv+b0IKSUuLi4uLrlJQbYH4OLi4uKSPK6Iu7i4uOQwroi7uLi45DCuiLu4uLjkMK6Iu7i4uOQwroi7uLi45DBpEXEhxF8KIf5ZCHFZCPF8Orbh4uLi4gIi1XHiQohJwCXga8BHwLvAainlP6V0Qy4uLi4uabHEa4HLUsrfSin/FTgMPJaG7bi4uLhMeP4kDeu8F/jQ9PwjYGG0DwgxWUJRGobiovhCtgfgENJxuNvxp3EsYzcW834qCC5m3L4AlOiPB4B/Af5IyHKTv/wvfPrb/x3uBm4Cd+rLfQb8cUxf+N9MH7Tyr3GMPRqR1ptN/i3bA0iSYaT8VMRaKh1Htd1Gw3w2QoingKfUsy8GH7qkmNJsD8AhTM/Qdu6LY5lIYzHvq8nqzrBtioEqoB5e9L3AD3a9An6gW3+/TC3zaT2s9h1gjlhLc7eEncBRYATgU6Bf/8CNKOP7KI7vEI1o684W/bEXcRxvxLVUOkT8I+B+0/P7gI+tC0kp30AfpRD3uAVc0oIr4AonCXgk4ttXFb7z/ODCK0rQuwmIN8XqcYF3lEO7nmS1BBqBwUhrmk76xDad63axko6JzT9BTWw+AlxHTWyukVJeiPyZe6RriacKV7iDZEq8IX4Bj8cKh4AlDiEibVjktU0dTGOItuYVUAwVm84D0LNrnrK8AfpQIj4IygqHUIs0ndZ4PNvIBrlkkb+BlB9n3p0ipfyjEGIz0A5MAg5EE3CXVOIKeJBcFnATxabHfcH7zlYP230bKWoaBuDQricpqB9VLhZjuYCARxuP00TWJVFSboknNQjXEk8BroArMinekJgLJUkr3Hxvssap1O/9KNeKIdqGBY7p3tYSh8xY47G2k2lyxRqPzxJ3MzZznlJcAQclkPkg4AlQBW/PrQuKd0wBT2RcMD4ffyLbyTT59X9xRTynya+DMXmyId6pEHA7bKxwgzL9vgrkPwtK5vay/EK7ssjThivkTscV8Zwlfw7C8eEkYUiUKG4UM8akpv64sWkHDMFGMYMX574QfC8i5vVm+7jJ5f3lTFyfeM6R7T+hU3Cy68QgCR842PvBN6B832UEfOEjsydx1/AtxvyF6r2EXCqJ+MYhtf7xeLeZCZzsH3d94nmIK+DO930bjFPAQQm2PoG5zHccvOr9El8vJXN76bqjJricMeFpTHZaXTGRrPyY4zVIpVsl3m1mgtz/T2UqD9llXOT+gTZ+svGHT7Vw2WRkhomt6bVKaNojeFxWcJR6LvtmcTfDLOA9postnAZeYgqd8hhtfSuobepgAe/Rsujp0HUFrPHJBC3yUhK3Qu8j9Ra5E8Ick/ktnIMr4o7GFe/sWWvjEXC7MdsIuBclst3hS1MGDEKzJmluVZmYt49OYfRbBRR+fQxNX2ydnEonKpPzBV5hRf9xtc4+ggIet5BnS1CN3yvbYp6buD5xx+IKeG5a33EKuJ6F+fYHdSxvaA/6siFkEjMQE+5V4YRnxYmwtWs18OkH8MDINZZwkivMonORJ9Q3DjaJP4lmcRqkwz8e77bTidOs8fh84q6IOw5XvHNTvCEuATdPWpahxLmpjuWt7cF0eSzLVMLuVYK/BH4WYctt0k/nBY+a4PQTFOw+m4XL9NcvQmhRLIN4xTTfxDw3Rdyd2HQUE13AszFpCekTcDOTg+4Tc8Yl8NiuE1T4zgffKwa8UNvSoZYpgx/Lc/TK2ohrP7PLS0HxqHpirAOCk57GJKkpuiWI9biLdx+kY7Izke2nmtz8/7k+cceQmwdQ6shV8YbYkSiTlXBuQFnbxcBmeHHuC9zNMFcF9FTNC4n33r5pI0UM0+WtYVrpEHczzHssADptt7Rwk5+xC4XBE4ThZzcs8mJoPLKDltanqfCdp+fBeeP5wibSMdkJ2fPP594kp+tOyToTWbxzcdLSShyhhMWTVZblRsHPG5YyxDTWth4E1ITltNIhBjrK1bJ9qJKylaO8VDaFx2UFl0UPpcBJm60sAf78Omy8ZzsAe/vXU1faTtuFFeqEobtTzrXM4RRL2LJrd7jLJam6KlZc10rqyVIVQ5dEmKgCns344CykkQ8C3SDelDBGMGmnGG7/fgrchoUeP139NezzrOM1nuNuVHXCt0QPAO9HWPVJ4OS9sHv1Fvgq1G1qp4hh2lgR4n//GicZuFAe/KDxXsqqHBq/az6GIDob1xLPChNVvCG/rW8zNhOalvR5wy/etEpwW24FYJJ4lRtyO9/lh+wTnyQ1Ou1+mPTuCGMXC4MTm1UglwkO9K5mbcdB0AhWPoxoiRskKqL5kN2ZO5a4K+IZZaKKd75Y3pC4gIM1rBAIZFX6Wxbi+U4n2k+DSz9EZMs7Xm5I5V55jwVMY4gihjnJEgZayynx9SqrXEN3q5hT8u3EK1kBTbWYTzQhd6NTHMZEFPBsRZsYpNr6TkbAI6C7MbytZ3j0J8fQTgXfGq+AA3yXHzJdbOGdzxezhJPMEWuV3/0iDDSWWyzxWCS7DxOt9piucSRLbvxnXRHPCLlxMKSWbNfFcKh4WEXzIizhJNojqdsEEHDFbLtzjFuiBYC3PXXB+PC4BdxgPL9BKsU828eV83BFPK1MtIYN08mu9X0fqReMRL6L3b6OUODKVKhqy4XdlMvVyQwwbi7J/Sxvbg+vchg2xmjH63j3a6r2TSaPL+f/f10RTxvO3/mpI9tuE0i9cCf6fRLY32WwvWUjcrqgZJOqSPjk9w8luL34eOazAtqkn0MdT4an9UcknUIOqRHzbB9vzsEV8bQw0QQ826TKukv2u0Ta35G79Gzp2A1fhdd4nplcZcf3GpPcdnRO3rGEM+e86oltidpkSNVJO9U+83Th7P+zGyeeMpy9o1OLE4QbkheAVI0/2j63qd+thxiWnO5Vk42c49J3qun96SFupWhEVh7gKgur/ZTQyxLPSdazl2d5nc4ST4xPGt8tWoRGqmK4k40xz2T1Q+dmcrohhilhogi4U8QbUtuoIRli7XMbX7ip6JVRE+VFzwtMEq+mcFzhzJdLacVHDV1sad0Newj6xUN845EaKscjXqkU0kTFPFOhh5kWcTdOPENMBAF3knhD4gKeCcvbIIIFbtwb/mhdxKmHpiqRETvv5b4RleLfUB4anRJTyBMZWaoE1YlC7kwRd90pSeOKd+ZJV4d5SM3+jCLgBnptFAbVvVwm2Ci38zh7Ain2qeSZzwq4fMcsqjsugQYDg4UxQgvNTSMMzL9NLCGz/u7JimuiLpZMpOc706XiinhS5LuAO028IfUCnsp9GKVLfQxe6t3K+jQJOEDrHT5OsoRaTwedhz1xxobbCblBokKWyLFkJ8LpqpKYP7jRKQmTzwLuhFBBO1Ih4KWWm5nJxG4kbEeUz1kFPIKgL+EU71GTxLbjw/d5K3PEWvUkkoDbjm0ykb9fuvIfxnv8ZeLYdd7/3/WJx4XzdlxqcaJww/h833FOPBqFqGwn+iBokcYQ+WhWt7WDvfGa4SOvB7lPhNRPSRVt0k9nh0f5wP2Ed/yxft+Ylvp4feZmSlWZ3np9bBfNXYbsrPJ4LfJ88Y+7tVNSRD4LuFMtbxi/gJssyeLJoc+tBamK4cUPXogQRx3D2jYXtYr1nlnAzXRDx09qWRLpqyXJN4Blwhs6iRnrCqE4yg1IjWVuWf4iemu6yabXnXpcOg9XxCOSrynz2U6Nj4dE3SfhAl4rO5SFdxh1X4kSokqCIX6GFV4Pr/R/Vy0XTZgNLG3UqCLQzDjw3MDcHs28Xsv6vR1nWCGvxfmdY6MthW1yO82HTVfa1igZ67is49N/n5KBXthJoJ1cbDdLrJt5PUAfbJ+7Ud83k4GZ+vvWYzTe48LJx3bqcUXclnwUb3D+wZ26DL7OBz1QBct8x9ULph6T8r8JWEXQ8q6Cl8qmBFuaWYXM/NgihE1HBdSD//RCKo6cR/5UBMMHra4T6zrKCBHzof5pXJL7U/L9F7b72du/PvwN6/fxEuy9aV1GH98RGkLHG9Uqj5fQz25p2A2b4/mcU4TcORrhingYztk5qcPpljekNv36UxiEgg2jtDWvoEAbpfa03nS4Ehbe4w9Y5PIPgqYqQbNfBsL+gFBLOYoLotkvGfnWJAAuHalG3JTBk4N+O3dkDhVHzvP3e0Ro02JrowigiwVckvtDStMmSqc8xlXDmjULb5XpZjz3mm7WpspeKDnSSwNHKPCO0nh6h7LIxy3kls8YYzTGE4LTj9vs44YYBshX8XY64xFv6/cz7cNBGKsqhCoYqy+kc9BD0x4l1m+wjq/5TioLczo0r5dqYs2gDDXxF82lomdelnh66aKG06ITz/3Q9KFA2wmiSndjVMJ71LBGVPPn14Gb6mUjwadJXmOjmEGnPEatWMkluZ8ihtmxuJF1spV7d32CFoeFqr0J1xum0k4dlximhi5qy1ZyUJ5jjahmt7zG87zGLdGiJjtb1ZWKf+5CTntV8+VmTQavRqrUSbBZzAidwtv5dDDOPYBVyK2Tn1HmFHR3FlUEa5wD0UMZ4w07THfsuDPixt3oFCD/BDwXxBtSK+AQsSWayWctbwg2NmxnGoMMUcxR6hloVc0Swkq0GmVbrZTB6tMHWCnW8j56s+JTwFRYU72fLhbQ06q6yVf4zrNGVAMq8WbxHe+oyUadu2Qjt0QLz3xWwLY7x5L6JSKhNYPWpD9eCgfaV9MrDrEE8PSNMKv0Mvt4Ck9dJy0nlBw1a1J9Z/03K/H08hrP0ysOoV0H8fdSTUIak6UJ1STXMZ8cN0NJUy/7WMde1tNWssLUMs4skFYxdkqkSjpF3E27j5N8EvBcEW9ITynSKCKu+38rfOc5zWKKPh9m/h2/4Ur/bNWL0hClSv3ei7IM7URKX69sECxc7GcWVwKx2Nop0B4B7SyIP8hA13oD7Sx0VNdyWnSO8/snhtVmNCx/g9tyK3vZwMAu1UzZv2khNZ93UTg0Bm+BthnK5Wpe4zn28RTeRWdMVjPxibmdW2ozVGxSJ7rmemkKg7T2/XRyyGG6hDxFIi6EOAD8FXBDSlmlvzYVaAUeAH4HPCGlvCmEEMBPgUdRe+GbUsrfxBxEVkTcFe/skM6mAMY+1S/fK1FCfBHk/xT8vH0pZ8UJ2qSf9ezlyTWHWHNwPwe/v5Y139vPoY4nkR2C0ecKKPxgDPEF3U9+mHCR0k8OTZvt/2OX5P6AsK+TU5NuepxOlgAnTc875THa++sAQk48oMIV6+Q5dYUxiLLGw5pLmIjkihokbOI04Av3E/ytA+uNFjvuijjEN7H5N8BfWl57HjglpawATunPAZYBFfrtKaAl3uFmjnwKHcyFCUszGezqYhYRL2gn4Ble5+W+Ebr6a5R74BBKaL8FPlqp8JxnzvfO0XVHDXyiwt5e9LwQ3kTBNBk5Xy613byPVrTr6rETBRxCBRygVqzkVtFd1JR2hS37M1BuoUFCLXBrOKYRlvhBL3KzUAK9meDEqVnATZ/xexYG68qYo3g2mGPHkyWX/iOJE3NiU0r5/wkhHrC8/BjBeeSfoc6hz+mv/61U5v0/CCGKhBBfklL+PlUDHh/5It6QewdmugU8fN/K+YJJXlW5r1Meo+fCPCVAVSqT0fBNa/cCnGCfHGaYIjwfd6I9ApdkjeqIYxcW6AUGYS/reU4Oh7lHzooTnB3fl80K2+4cY1l4iEg4xu/RZ3muM9BYjrYHVssDtPb7GKsqZL9nDWsbDoYmHhXD9k0b8XzcGXytHj35x0omilwlQ3YnOJONTik1hFlK+XshhPHvuhf40LTcR/prYSIuhHiKgA/li0kOIxHyRcAnongnhzgrYRUMFBfSVqx8vUYizrPCG9ZV3hBiQ3xr6OJgx1rESpPL0asiS0BFhPAw/PzdpWhnQZufrm/iDA7Kc8qJaiQzGVa5nasJaN4pWcZxbhXdRavHx9pdB0MToXS2tO7mpq8IVqmJ1BvnZjB90zUGGsupbemgc8/DEUbkFseC1IcY2vlvbJ3uUso3gDfA8ImnC1e8s0OqxTsxKzzihKTub135bXg/Rq2SW6IFDZAIxJel6soztxetBrQu0J7QF8xRqztetJ3w0qat3M0wVEHj3B2AOsmt3XUwNDwTQiKCasVKCnfC3k3rAzVqtvs2smFKC6+PojJKy2AvG5BfFIgOifBL+M9AN3Tu8RC5omIi5G+4YbLJPv1CiC8B6PfGr/MRcL9pufuAj5Mf3nhxBTw7ZFLAY2Du7m6aVJv+k2sskrVxrWLh9/wqbrpylJlcRQt3Gec12maYJF5lu/CybK7KgN19bgu94pByK5mzQKugouU8TZsFJZ7ewOeXCS+yQnDON4c9rOf1UeXSavTtYL9nDTfOzQCg1tOh9pddaKeLLcmK+C9QE9bo9z83vf4fheIrwB+y4w/Ph8nLXKhxYuY+0tP4Ntb3tysrG4FiFU2y37OGGrriDvNbSju1czu4/eqUkBjvicZJYK1YyXSxBW2+CktkkGAcfhlQCa+KarRTcOP7M0I+r90Lb4meQNz8MuFl95otdFGD+IJE/LPkKjNZ1nI8fDI5IulsFJIo2dGcmCIuhDgE/C/gy0KIj4QQa4HXgK8JIXqAr+nPAX4J/Ba4DOwDNqZl1HlPrgg3pLdjeaICHh+94hD19jNntizhFMuEl1+loVRsrmGeR7jCbJq8AtkjgsXFquAPcrWKlW+Kvb7rB6eqGi/dgB8GmstZwkmoh4LuUX2p7GdFOpk8S/bJdesbckfA0z1hmWx3HpMlbilWVXu6I2BJJ+LBdGqcd7bRlhLM9PQrHWnyxgxrDl3Hm8AHcOB7q1XkCqj9tQrYgMqk5arpE+NJ+on0+VSSyhPOhOuxmesC7nTxzmSUSQoF3ERno4elciut+JjNlZCMxWi4Am6PdkK/Xwp4hYpeSYC7ZCOT+rcxNlYIjYTOX+wxlkrFpKaZ/JvgzBMRz2UBd6p4Zys0MAUCbsYs5oPwg9ZXANjnewrPm6YIE5ekMcS8hvcS+lwRw6rkwUVCBTxAqgU8P8mDUrSugI+P+yLcskGKBDxa9UE/cFE1YRj9ekEgq9Jl/MwRa+OO+AFYNeWQemCEJBqTmQkX1cpeLoITyGERz+UIlExEnUQSZyeItZV4f484XCh2DR3sIh26Ycrl20y/5xqX5H4elxVoO+MfsYs9iRT2mjxVhRTKrwpGnp9Eyele07u5bIVnVpdy1J2Sq+IN6RNvpwhyIoz3t4gwiWnG2uQhrDsNDFPEW6KHt8Y5GpfE0D6EN1jH9eqprGMfAw+WZ2jLTk3fT44cFPFcFfB0iPdEEe4oFrhJvH97UfB/bJbqNT9hNToog6Oa4Im+EcYGCwPp8y6ZRbsfNvZuZ2//epo7CtWLO4lQnzzeSUKnpeBnboIzx9wproArnOQKiZdkXUjxCThleiW2poUc3SzCe1pWQZMmeB9VZrV2bgcPJTEal/GjfQi767ZQV9quSs/uJLQyoktC5JCIuwKumCjiHQmTgJt7VFZCc7fEc66TJ/pGQt0mZbBs03E0U4GTZTYFsFxSj1YT/lpzt2TS347Q1rxCRabYFdEKYP3fp+pYckJQQWrIERHPRQFPpXg5bSIyGtMtt2Sxm7gONnuoHeigwD8Kq6Dg8Cjyt6rh8cbq7YwNFoIXGlt2BLr6tHWs4Or83DySchmjzsxdspGX+0ZUUtBRGNMKw63vZFq9hZAL/4/UkwMinot/u/w5y0fHKtip+t4x9vkg3KSIaaVDrG46wG9K5wdild9jASVze3nR8wLTxRaWbToeKNJUJ8+5CdxZ4pZo4YXSH4Y3kTATLTQ0hIny/4oPh09sugIe2bqItZ1Uzr474U8T6gfvaZgHXriyaRbz3lGRJYtkLdrHXn51L8yUU9kH7GMd8+fWUMTNQOEll+wwSbxKhfTBXOhpnhdqeRtlgm1xRlf5xMnMuB0s4rkm4JkWb+P3iXSQOEF4EyWxfS4fF8zhHNcXT2W+rMHz8IlgmVg9VX6f+IS/k0s4xRJqCW9J5pJZjBNpc7des6mPYCefEBGfTGisuFUQUxEmmB+hhg51p7gCHp1SqJwMxUb/QfMtV4k2dpuU+kEQ+yQ9F+axT3zCXtZzNUKd77dED0+fa3EF3CE8LivUg0oo0EZZvelAsNljiEvFut9z+fhOHw4U8VzbUZm0eC3bqgJ1oJsP9lz7/ZI8+fQB3arLzCW5n/b+Ok7L1Wir7RfP99ZpucRbooeKueep8J3npbIpqlm1Nds2QDQht/vvOW1yM/3/R4e5U3JNgDJpgVu25YVlLcdpa1ih9zrUD/ZBCP0dU+mTi+XCSWZdsYhSmXAQWhqfDoQY9q46hJaCkbmkH+v8hHxQIJBB33iIj9ws5J+Suz7y9OAgSzyXBNwBHXf2QNuDuoBrKKtcQxc6q2We7G8byVVjfT3ebSTq9onSpcfAtvqdS65gFMwSH8jwGjd2tXAqjStP4xjKxbmf1OIQEf9CtgeQAA6qfWII2GFU8SB/tIVTIbSxRDWSuKfYXx8hFO3lvhHapD9123FJO57vdKrYcSNm3EjSMmMS8hc/eCGBUESnkF4D1WHuFKeTLQGPsN3BCPdA+Oy+QaIHlCVD8qIh5OmsMmdzsrD6Sy0ZmQBjFwu5WVrEJblf+VldHI/2U5BTBaLM1GGsEpXJaW6WrO/vH3S8oiJZvNEMCqfVUUkvDrHEcwGnXLZZRLgYSo70slHMUKFa+muKONwRUTEJuJdA9mPQZTPe9UfZphkbAZc/FjQdFRRoo4ExrfYcYI2oZj170zAul3ShNRE8GVfB2y11FBweDdYY1wW8YOcoBZWjbp0VC66Ix0U6BXwcs+m6qA3sKqf5sH5JGnapmYzYmj5jiLbhe6+3biNVYh7nenSrW/zBZLnp3dYN6zuRmtYu2UV7E9XWrYqAofAMr3P791OCx1qlEvCXyqaodP1A3fdcmkdLH66IRyXdE5jjFHDDerFzp0QU83hupnUYf656eHHuC7A50fVHIs7lzFa4FxpP74ANsN+zBm0n+EpbafKquim35Va05iibdHEc2hPgo5VlnuM0eQXyLcEaUc3G6u0hwj52sVA1Vb5ot5bx/EedcoWdPK6IR8QpO9duHJMDB7f/9EK2N220F/BodSpiYXxuA7AZGjft4AfNrxASwxfX+hMVd5sx6BRoo8zmMn7fQnrFIXgcDh4J+r5fPvKqujR3ySlePvcqv1yjmlZrP1WvTRdbWDb3OE2bBVTBMs9x9UYlynDJOZdK+q4a3InNrDHOpIRuoAq8DWfAC6PPCQp/JIMRK+Y420iz/bZF+Ak9CRxV29nbvz440WTthRi17kWSFIc/HtMKOdmyBB+teO4H7d7Qj3z6n1I8BpeMECkRq1YoYV/mOc4D/I6FDX4kgh0tjWxp3R1jrRNnctMV8TAyYYHHK+CRxvKpihIxkiJACXgVoWGG5rhbkwDXnu6gs8ET3ZoxRNQLsl8gBm3ieA1M44hIvCIfbT2D0Na8gn2a+nPPl0s5K04E3n59NM5tuOQUv1yzkkcPHuMmRYh/kvAgEdwqExPXnRKCU1wocTJounmhxNOrhLySoKvDS/ASVJ/l72z1qM/b9JsE03P9snX64mtUeM4j/6dQPvHNpnWb12HTTSdkndEEOtL75rEA9EGzJmnuljx25ITNB1zyBe0UlMvVtByC9v46NrCXkiajmfKnBLM2c7+I1XhwRTxApgR8vFZ4OCWne2En3HhnRsBXPtomkD8VFGwYVa9tICDuJb7eQI3tkEbCZiE1uUwGmsvpaZ2H2CF5ce4LbPdsBC/B8D6zha6HiQVOHnYnCLtbogzC9IZrlMvVasLLJe84sHg1ay8cZKOmIpH2sJ6BkvIctsLT4xcXUsrYS6UZIWZIeD6LI3CagIP9mMwHgWlysFK/L7M89kKF5zw1vMehC09CN4wsn0Th0BiP3nNMtcfqQ4luN+F/Dquoe6HW08Ey4eWG3M50sUVl2+00faYKKprOczfDzOIKhxY9GXTlJOI3Nwu76URTceQ823iWdexjJldZJrwJrNTFyVjdY6CycMdWFQZLKwxCMNEsliUer088k5Z8IjVf3kDKj2N283Z94jkj4FY+JSDkVnE0TTT2MI8Nnr0c/Ke17PA1cpIl7L1nPW0dKwIukRJPLwPN5ZFF1pQKPY2hgIBrp0DrFoji0Gw746TRedQTFOO+4Dpiinkkt0oVXOmfzdmyEyyRbmHZfOOsOMFueY2BC+XBuZ3NRBBwF4MJLOKZ9H+nWsCj0Bf6tMkruCm3Mr3hGvUcZQHv8QC/o8kreLlvhGmlQ5xlPvcVD4W7UgwqlQvmNZ6njnbu/f4nKtLwF/DoT47BBdSfblB9toYumAvMhUPNT4ZOoJrFPB6ME4gX/JsWclp0oi0FzU2rz0s2ihnBxDUj9d42iiqVVQxzuznEBPWJ56mAGwd6X/C+WZP8oPUVBi6Uc5JH9DZlWwCoK23nCA204kM+KAJpzi82vaB86aaEoiM00CsOsU98EojF1n6qh4EZ0Sm6K+eZ/m10sQAfrSqG3ez7LjPdYmFexnQi0Nz5zLykFOiUx4Lp9nlJ6v3iE1DEnSrgiWLyiUdyT5jKtBYUjzKbK8z7fk+gw80vd62k5vMubokW5iw+FxDiVnz4SlspqB8NTICu4w3my6W2mynx9NLoC3aWBzjNYs6KE9wSLaE1V+oJdnGJ9EeNIPLejjNulcI8ph9lFDRVxXQDu5iYYCKeSf93ogIea2wJnMHNESd6tMi00iGKGIZvBRfTNsO2O8cAeFVUU+DrLnsSAAAgAElEQVQdpcA7yjB346OVl8qmIL8peHtuHT5alZvEwkPAevbgoxX5TcH+uWvoKJvCPr3HpbaTQLRK0x5ByaZeZbGbJ2CtNzPmydU+WCa8dMpjbnp9vmNxC+Ze+dnMMYFE3IkTmAbjFPBo8dX642Yxg/XsDctyNHgfqCntore0nCWmbpRaFzy26wSTxKv8qy7MZlbWqC7mp0UnWpea+AyZcvwFFFSqk8NdspGzzA/N9IwVO25QBk2rBPPlUpZw0k2vz1O0U6YmyoYRYhwnlZCeypm5TUwRF0LcL4Q4LYT4QAhxQQjxbf31qUKIvxNC9Oj3d+uvCyHE/yOEuCyE+EchxJ+l+0tEJ5NdeNIh4ElQjKpx4gUqYfXcAzTWxK7ut5R2WvExR6zla1OCjmdNL3r1M5vPaBbj/Kw4wUOm5786AdtKn2FW6WVa8VH0+TAVm86HuliixY4bf+R69fSxNbqLxiUv0R7RH6wieIwYuQdalgblcOKxxP8IbJFSPgh8BdgkhPh3qMDuU1LKCuAUwUDvZUCFfnsKyOI/zsnuE4hvfDE67FhrjBhVDXfCMt9xqILWfh9r3t2Pdjb6liaJVwMCOZ4U9vdNj08Ct0QL23iWZcLL/7hzjDWimoL6UUpaemnaI0J86SGYXzOs918lPy4X57NOTqWpSvCRZxpNmlCGiFflB1T4zifgVpkYdVMgDhGXUv5eSvkb/fG/AB8A9wKPETTOfgYs1x8/BvytVPwDUCSE+FLKRx6VTFnfyYo3pETAzVgPbr3OCH5VxvMKs7La8d1I4ngfVUN6VullzjKf3fJaeNVFu8zRPmiTfnb0NoZY+i75hTGXsk98oowOLxRsGGWNqGaYu91eqjYk5BMXQjwAzAfOAKVSyt+DEnqCqnQv8KHpYx/pr2UIJ7tODJIVcAvFlnvr6ybOnPNyW26NY7vp53rDVJZwinbqVEcia+q+Ff39Mx978dEaYum75C/afFSd+L1TaD4sGWgoz/aQHEncyT5CiCnAMeA7UspbQkQMA7J7Iyy3XwjxFMrdAkyNdxhRcFL1wWiMZxLT4kaJkJpudz+9+hozucpSqdfdfiLO4aaBfeITprMFo5RRia+Xof5pjB0ttM8+LQZ5Q6B5AcInV13yl3K5Gk0cAr/q7jN2tNCyRC4m6ZSSymSluCxxIcQXUAL+36SUenV2+g03iX5v/JofAfebPn4f8LF1nVLKN6SUNVLKGpiS7Ph10i3g43GbGMRy8cTqCG8R8M0oX/JR7ItY6bVOCryqL6FRZ+T5z3+UVQG3Yz17qCttt5/U1Jn070dYJGuzMDqXTPK4rABUlMpdspG1HQe5SzZCMYxVFeKm3YcTT3SKAPYDH0gpd5je+gXwDf3xN4Cfm17/j3qUyleAPxhul9STifZp6UzYgdjiDbYTmX6CjZGtpWdXBZerK23n9oUpnDniBYJx4U7hIWADe1Xmp3mC0xKdMq10CM8Rt3dmvvOW6KG5WyJKJVuad8NO2LJotzquA1dpqUy5z33icad8FfgPwPtCiHP6ay8ArwFvCiHWAr1Ag/7eL4FHgcuo02Ya+q1kwvJOFZHGmoBwR2C17wDDFNG2agV0g/yFYJI2wjuli9nrWU8XCwLLOs36NngfeF+fzJLfVJ448V9kaBehYlVTQ8vGAF0yTlOVoLlehmQcu8WvIhNTxKWUv8Lezw3wiPUFqWrbbhrnuKLg0MbFtsQj4AkkL1gmLA81PKms13pU7DVwe+8UtCbwySIOnlvLjurGYOyt0/mRHidsCZssKHZb9kxoQuZJXCvcSg5VMcwH8baSpIAXE7RU9cJQPd3zmFQ/wktlan7hrDjBWUB7syVnLFjtERUnvJteVY5UZ1bp5SyOyiWTtEk/nRc8oTXqL4K9FT7eOuL5QQ6IeLrEOx2+7kQiTyYHC0IZzRi6wz8Rhl252D6gUlnha+R+Dn5nbaBruFPdKJHYJz6hRnbRNReG+qcxrXQo20NyySDLhJdloMrRGin3VTE+NMFxeO2UfBLwCJRBweFgtcCoRHt/EIRHMkxRQMBzlV1iJTO5yqzSyxRxk9lciZlt6pJf1Po6eNHzgoq+ygg51l/XhINFPB0/ajqiTeKNkIkwkemHW0V3KWs6WuPiSDHhlkSZy8zihtyOdj2OITmUn6EssrsZ5m6GKWI4q9mmLplnmfCylw3BDj9AfvnDU1dX3IHulFSLd7pCBBMZp3WHhfbHnPJfb9PYsoOWxqfVa9buN3bZjIaAG02JgYq5qv/kks9PRqxWmCs8Wwg3eI9hiqihi1vZHpBL2umUx2jbtSLoVnyQKP5wFwOHiXiqBDydsd2JjjHGGdcPDEJL1dPB4lV2eAmGW5kZhNq5HZw54kWrgrOoW67z+ihMF1uYJrdSxLAr4hOAto4VwXBCPzHqpORipmZ6cJA7JRUCns7knGQSixIoYOUn6Be33irh7aa68Pd1C72zw8PCBn+CY8sN7maYabiTm/mO9m1Vd55iqD3SYXrH2tnexYpDRDzZC4L7LLdUMD3CLVESKCFrWB5+qG3pCNYCN4n18tZ25Tox+g9a6nFfZSblcnUS43Q2j3CSJZ+7ne3zHe2nqu78yLcmMYsrbnJPAjjMnZIIDmnAEEYk90mUmHBjUrMPOls9NPp20DKo+8eLCXSRl98UiL+WQV+47jusndvBMuENFJTKJ+Z93BMMwXTJSxbJWk6LTm6JFu7qG2HMay1yZbXCo7lSJlaMOOSciKe6b2UqiGeW2SLg1ugTY+JylbqknC62UCLrwaO6zC/uf4eXyqYw+lkBq+84wBVmcZMirhTPBpQV3imPqfoj+cZfZ3sALunmtOhUceEayjhxrfCEyCERT0TAreJtFtrx+tYSCQ2ysb6tmZfmx34Y6yvkoDzHjY9nwFdA+xB8spUbcjt8/gxzxFq2yam0U8fJ0iV0sYC7Gaaeo3lpiWuHVKSKS/5SLlcj3xGIQek2fUgCh/jEYxGvgNv5r3XR9U42PY9XiEttbvFiY33bCXgZYf7xngvz2HjPdvgH9dJfiLVMF1s4q1cg3Cc+oVccYo5YyxJOMYsreT35N55WcS7Oprlb0isOIY6EtRzQcSc0Y+FgS3w8lreBIbp6intAWD8llcH2gW1YMQu3ucO7QZVe6F4rDLxXUK8UaxqD8Gv1snEY203vTRdb8MlaZnM5L0ILXSYWy+Yep7lSqszMgBUezZXihhZacaCIJ2J1R8Mk4KAOEGOSkMnE73NLoEiVGbOlXYkl84zQBB6vaXzAS2VTeOazgrjrnnjqOuG55Ibp4pINLsn9HNr1JCzC4kIx/y9dKzweHOZOiSbg8Yb82bg97BrxMtl0syP4XqPckUCXbcv2KlFdeMosN32ZsaOFFHhHKdnUC1Wq+cEluT+h5g3aCVwRd8kZ2qSflWKtsr6NapyuLzxphCr/neVBiAcl/I3l1RT1oqzU740Y626UgBqFdSIdPGYh3gMcJo4sMstnDbGut3zW4lLBCyOzJ/HMHdvYfW4LP69eGugO7+KST2jfBnHdruEDhF8d21nisdwp4wkxzLSrJtaVxhtI+XHEZsYGDnOn2Al3kh1wDKFchTpYNquOIS/3jTC2uTDoWolmYRvvmdPdzct7CXeTQHiBqkFMoVOoE8tFAu3UVs89wDr2MUes1Wt/uwLukn80+yXNhwkVcJdx4xAR/xOUgFsEu3Jy9EQPs0javQfQp7IgF/AeoPzNzTtlIIHGWCaAl9Bt6hmTJUd6GWgoDxV+r2nbZpGv0tep10EuqB+lrrRd1YYASjx604NBeHtuHa34OFi3NmeaN7i4JIK2E0SxVFezrnCnHIeIOCgBt1jVGsqfbGAVbEvmYuCxedJwFbzz+WLEtDFex/JZK8b6BuHckTlUN1yCYmjyCpq7ZWjNEkOk/Zb1GROZlcFx7CtdxzBFDHmmcZMianiPK3NncZWZnBUneE5ejfyzuLjkMJfkfsSFJ0OvWPsiLe2SDA7yif/S8mqcbhQ7S9zsz/aiQvnqRwOtywLZYQZmK9oQaIMyYAPqILxIaANfTb9Zl68kaLEbz8sIP9kUQ4mvl5lcxUcrt0RLjO/s4pKbzJdLWd7cro57qzvF9YlHIOd84sYPaPjFI31BQ9z1HW53eTZosugHgaMw1l2o6hU3r7DEpEZ5rFPgHWXsaGH4gbchwvbNQm+IufkEYFrHQGs5A1XlTJs7xD7Zyj7xCdp1cr4euIuLmbPiBE0I5co0ggoiuUJdEsIhIv6vpsd2Z0PzhGcscYegwE9WB4xumbctWmEzI24i2gFlWBAxBD+MYqjd1EFng8fef66P7Tl+xHzOMlNe5TbtTOLVOFYepBQ3qtbF+TRtFipGvPFJZdgknb/hYuCgOPGPiHwpdMN0i0S/6WZgOSBsQ5oi3XQGUVXVLhKfaNucIK4yM/iaeQx61EpB8Sje1jMMdJTT1V/DEk7FsaFQGpsT/oiLS1aYI9Yy8pNJys2YSP6Fiy0OEnGDWD6tG8QWdbOYfxpqAceV2mu8r98uRnjdKvhmTEI9sKhcibfhTjH50Gs9HcpVo7tbbj88hWd5ndtyK1oCWq41xb+si0u22XbnGPJLIrQuPhAa3JDq0hj5iUPcKVbMQh4rDd8s5NY4836CBbDQZ8ijpfVGOmjiEXwzplR/P1Gtjc4GT8hz8ZyEDpjluRJXFuY6OZUf8l18tHJadMb+gIuLU/gElQinV/B0/ePJ4ZDolFmS0ABAC+MthmWEL46n1VMyVkGMOuLmTvVGeKNeBGt96V6miy18A+iVtRRxk4opPbw+iupk/2u43jCVdewDYAFdvFz+KtqHSQzT4bj+/vxmCfAXh6UKJw67Uk40QsWNTnEoxo6JR8ytUS6QGgmI12o38ykhQm7N+jSem6NYvHC8dAXt1HFDbqeXVp7ldaYxxC8vraT8ntVspIb3GhZwkyKGuZsibrKArrwU8GcLYfKDoHVleyQu6eIkBN0qYLHI3VN4LHJExA2SEXNIT4cfuwPLTtgNi8Ii5mar3GjPpseOP/b0CZbvUDG1u//XFjr/Tw8VvvNwA9bePAiDqgPQ2EW9hK0HhijOSB+jTDP5F8AQEGdFR5ccpRv2f7CGtQ0HddeKG6kSLw6c2IyHaJEsdlgnQ9N12WSNjjET3wH5ou8FNrZvV4J+EcTdEi5CT+s8Flb71QHeDWP+QrVMH5xlPu+xIC874FxfPBUqsj0Kl3SiNUPTKsGT7xyiYOeoG7GSIA7xic+QsGOca0lVt3s7krVx4+h4b/jFi+HtI3Uqq82aFFRMoP9moIEEwc9RpeqxbBQzkhyncymXq1lAF2+JnmwPxSUDNB+WvO2rY3lJu6XXZiaaJeemT9xBlvh4f8BErfNESNaCt9tJNhZ5serws7zDlJZsxKUbt26YVXo5NEzSlEE6k/ysv3KVB/gdM7M9DJcM0OxXV53LG9pNrybZlGUC4SARh9ScCT8i/YKeCDHOtro1PTZYGKzyZtSWMG76az0N84KfM1np2z0buUkR6+RUtKWqalw+cFtuZYhirjAr20NxyQCNHtPVuLUnrRszHhGHiTik9pImXYKeqGUeRch1VwlHCdZXsVZ560MJvDn132Shb2neTc+uecznLAvb/ezY1IiW4xmcS4D3qOF3PMBlZqPdn+0RuaSbaQzSpAmWHTnO6IcCdhJs6hJGPk7jJ4dDo1NukPqdlEhkSyIkM1ZL6CGEineM+uhAMCzReIwqprXEd5JboiXna5O/Io9x2WSBt+Rh+KRLKJOEqhdUK1YGs0bKgItGpEo+hRum7nvEtMSFEHcKITqFEOeFEBeEEM366zOFEGeEED1CiFYhxJ/qr9+hP7+sv/9AckNL1yRDuizzWETYaRrKyjYSHSJlrUV7zxD2KvLC9fAQcJlZDHM3w9wN5M9f1yU+dstryBJB4+nxBjzkP/G4Uz4HFksp5wHVwF8KIb4C/Aj4sZSyArgJrNWXXwvclFLOBn6sL5ck6QwJTLWYx1uky4IX5UrxEu4qMd8MzJOaBrolLvsFZ77jTXTgjkK7DlvlOa70z2bgQjlD/dPoooZ1cmq2h+aSAbT7VSmJgeZyxBHJUeoztOVMR6akjpgiLhUj+tMv6DcJLCZYGfhnwHL98WP6c/T3HxFCxAyTiU2+WOaWwlx2Qm1HpPeNCaAqeHTxMbSfqixHrUa9vUjWxj1qR/Cf4Er/bDXRO6gmfIf6p7FPfJLtkblkAO1DuK91KJAnMfBgeRJrSWe4sfOIa2JTCDFJCHEOpU5/B1wBhqWUf9QX+Qgw2hjcC3wIoL//B2CazTqfEkJ0CSG6YMT6dgTSebZMh2UeCZOQx1sVEUKrMRodg6pg/6Y1lHh6eZXnAXh9FDa+u51OeYy9rOdxmRvZMtqbMKf9nMpEtdRe75THsjYul8zStMrO5jPmkMxRKu7kJsQ5sSmlvA1UCyGKgLeAB+0W0+/t9kBYRpGU8g3gDTCSfeIl3en0qZwAtavjYmAIebRUfYgaJ1sGFZvOs7b5IPRBNZfgsGr5NtQ/jbHBQirmns+ZRJlJ/36EsQ5TByV9MnesuJAHSn+XxZG5ZJLmbqkiUwwCV6puKr4dCYUYSimHUYnfXwGKhBDGSeA+4GP98UfA/QD6+19EFZ1MA7limSfoJw/BctAaFmollDT10tMxLyz0cGBXOWN7lDU7myu0ST835PZkB59WtDdVVma5XK0scLvei4Owt3+96xefIFTMPU/THkHjkR1QD6sHDkQJNXSJJzqlRLfAEUL8b6gQ3g+A0xCYdfgG8HP98S/05+jvvyPTmtufzlookDoxj6crUSRsrA+/3mxCI9Sv7idQU4VuaOtYQWeHh5M8wiW533GuFe0J2Mt6niw/FN71yJT4tL50L1ddv3jeo52CNaKaZwvhdzzA6k0HmCPWIqcIk5C7iT9m4rHEvwScFkL8I/Au8HdSyv+OalnwtBDiMsrnvV9ffj8wTX/9adAdtWknU2I+3nrFyYq5yV9uSvQJCLYluzNkGT2SZZgi5n0/+64V7U24SzYGJl07OzyqGYZRasAaMz8ILReedsMMJwDaI+r+9VEVL37wYxX0Jv5GqgiuMPdiLvrFU3skx/SJSyn/EZhv8/pvgbDQBynlZ0BDSkaXFOlIFLKSrsQhA1NHokiYy9laS9tan5cpt8qRzxv4lQPauGlPQKdcwi3Rwst9IyqGyRBvM0aJXoBuWHkd/uSepZwVJzI6Xpfsseae/ZyUS2gSgub67BfrcyIOTLtPBZmK+RxPtbRYY4xklYc2cbZ9DErELY1ot905pgrw25DuC1Tt2yqJB1QscBc1LJK1vFQ2JVTAreGWJh/5wnv8PHbOFfB8Rnsz+PiZzwo41PEkN8pnoJ2F1UcOZG9gDsZBpWjT5XXJ1OVWslZ5POOLo6St+XEVUB+MUrn98BTO91bEjFJZJGvxfNyJdm/UxRLmcVnBU+xjGkPUipWUy9WsbT0YrBUD0ePgy6BJS0GqgUtOsFteU9FVF01F4YqhtqWDTuFBGTJmAyeSQZRoz4FMEa87Ja/as42HTLhXIP0ulgTQJzgHLpZDMUx6d4R/mTIl5sd+xHO03vM7dr+5hesNU5NOsNGWgmYymL9msv+1b4Po0AW82zJmM5ZWXc07JW9vqnNdKROAgQvlysVmRF2h7pcJL53h0coTnjx1p1jJ5Fk2URfLOOquRMNwUQyqnp1/PbI9Zohel141cE7DObqooRSV+TlfLgXU5a0V7RQhFRNvy60hhRa06+pPOdBRzpmHvUz/ybWQydaI2ao25Qae4XXmy6VckvttPuCSDyyStTTO3RE6P6JHWjUXS9w48XAmiIhD+qNXzCQj5OMYm1UEzVEqfbB8VzvTGOTeI5+grbZfRZv0M9BRTlvrCq70z6aLBXwst6J1wYr+4xyU5ygcGgv7nPYIzPneOebLpbzcN0IrPuZUn+OS3M9DwKdzUGGPfhDf1K2oYkJFus9ys/t+fapF3Yr+4wxTFP9v45JTnBad7H54CxUt50MMESCyy22CMwHcKVYy6V5JpWslSsRKtJ6EenTHDy68wpWG2ez7+jo4NIa2GjoO1jKby9z7nU9YxLN4u88AsK90Hev69+k+yVdU0lDpFa7fMxW7vK2eC/NYPqi6sfRcnEdB5SizS6/wPnBsZD80EvgDDnSXhza+sMMclWKKtJEHBKPLCyj8eCznS+26REbrUrHizV6T68QV8IhMIEvcjJMt8niJcllpCKA+wUkVFBSPcoVZbLtzTLlHfgXreIPLzKbjJ7Us7n8nIK5rWw8yrXRI7zpO4A+0h/WAcqEYlMvVoTHrOkNMYwlwqPXJ0Lh1cyx4NKzvlwHPqQibVE+8ujiL5sOS5g2u7zteJkB0SjQymSiQiFUeaVxWS1yPUDEscaPpsvG4CqgE+WXBxurt7K7bwkvtWzlBHZ0XPEp0qwjN9DRjrNfSkHkJJ5kj1vK4rGArr9HWvCIgurUtHUxjiPb+OpX6b0xORXKTWLFeVZi/jxfkVwVaWNaCS76wW15joLU8OPFtGAgQpXHyeKNTnBiZAjnYKDkb5G4N4TAMAS+23KqAT1QK86S/HWEvG9guvEGr2A9ve+pC/dR2PshBKKgcZT178NGKthP2soEihkN88MdZQa1YqUrJGvSFrieh5hfmCdBu+Hn1UrTrcFCecysb5hm35VbqOYosEFAP249sVIWwzEaKbTXDic0Et8TNZMIqT6U1brLCqwiI9u49giZ5jYGOcpq8ghtyOy0dT6tl/equsWkHwxRxqOFJe8GEcItev6/1dLCUdn7Q8QrbPRvZ0rhbnQywWb4Y2EPo5FQiWLJOQ05MVeqksq30GW6JliRW7uJ0bsjtvMcCOhs96oUylKgHLHLDqp3YlvgEnNiMRKbS9dMQR14MbFaujo1VUk0klkGzJmGXvow/uOzud7Ygjsj4JxeLYfWmA5xkCW+wjgaOgB9mea6Er8NSRjaigJtfizQxay0fYPns7f88Be1QhM+65DzTxRa6+kaUG29TLwO7ytUJ3Bw/7uKKeOaJV8jjOKmYBa4bhiqnhZWltSbNMAgdi2uhhcjZkpYM0HOb5lB94RIMQnX3JQrqR8EPy/3t9uuw267ddqyvR4uy6TO9XwnLPMfRvFGWd8l5tPtB+6spTH/3GkXcZMCrktdGlk9iyp23yb3GyekZ6wT3iVvJVCz5eC/zJoe5FuQvBHWl7cHoD1M52sCkpf6at+FMqNhDuNiaLOytvKaeH1brGltVGF410cpFgmOJ5gM3Y7ecxWI/1zIHWSD45fdXBmqxuOQn2ocq3PDGmhlsYC9Hq5RnYcp3blvqi+diJcPU4VritmQqlnwceFG1xI+qx6JYd6NA9HokRiQKNsvYWcSD0HZhRbiVHI+FnSyR3CjAn/Wf5dbX72LbE2M8hCpuH6mol0vuoy2FST8eoYYursrnkd8RCCSsgujJAqnum+tcXEs8Ium2yMdjjX+qhLgeJeZm0bZax4MxbnaYP6uphwXFo2pbxYRHm6QDm5OEXCyYVXpZxYqfhb/8rCAg4Nr9aRqHS0awdp6aL5eyW15j0t+OMOYv5CZFLOEk4rpUx/5O29VMSNzolLhIp1Uej3/cvH1TdIrhUtlMaMJNzDTlaPUnLEX3jW0YkQGgTh4RTwLJ1LaI0kfUWqHRiFLZDLJCMGnSSCCccWT2JLbdGV4awMW5GMXSmrslTVWhgRid8hhtjSsCTcHlMwKxUAaT0KJGqDitgmEy/nA3Tjz/MYlokyaCzfIs7wW7Apm6A0XEsozVqt+MjYDHu+44t2nGeqLQrzRkt1B1WSBw4nIFPPcIVLvsVpUqmw9LOuUx5sulKonMME6q4NHeY1AFywaOW9YyHhHO/VwRV8TjIt1t38aBLqi75bVgh5wwgU0GSzs4UK6VkPCu8Qh3jG2asV5Z9IHwSwr/g2TsaGHgj97cra4qy2WEKl8ujiNQAdMQ64vwHD9ieUN7aNmHzdDWuIKKpvO07VqhfyiXIlPShzuxGTeGkKfDtRIr7NA80WoqhGW4GrpVh/tw90YkgbU7+CNlwH0KTA6dDE17OVB9m2aMyU7zvTmMsozAyew1nueZzwpcy9zhaGdhevU1Br5cHhTsi+A9fCa4kGWyvadjnusPt+AQEf+3bA8gAdIVuZJkIlAxIVEqwfondkIbzXIxv2cV9GRFO45eoRGxEXID449dZnqtWJUPuMIsesUhtiW5VZfMoc2HjczgLtnIlou7o3d6Mov5RYh+TE6cyBRwjIjD+P7wmcYBIYjGhCYE3RyGvzrsAE/0sjOaoMdaPtZ7iezjKEJug9v1Jze5JVrg8O7g1V60ifkqyL3GEOl1+zjMJ55LPq50+MmjWRCW7RUTDLU6irJONkNolbdIzZYToT+OW7LrSxCbP3XTUUGBpsIfb8utia/TJSs8LiuAYLeokeWTojSA0OdKBo05E/Pxk/sTk+PFYSKea6QjwzPOS8Eq/T5gedsd4E4nnrFGsLr0UMMbcjsvlU2hYu55JolXUzw+l3RwW27lz/rP0twtOXnHEkDPwjSIOjEfqwTtxHKlgCNFPFcEyEymhNy0naOA3xzNkUvibSWJcXth2ZHjtFx4Gm0pqjxulKCUWP1FXTLHy+Wvqq5Rflje3E6b9Ks3Yk7M5+Lxnf4xO8gnbsb44rniI4fU+8kjTXQmesJI5gSTDX9/tH1u4xvvhrbWFWz3bYRvwcvfeRXtEGg74dPn4DejKh1fexMWNvjpZIhaVqb3K7jE5JLcTwd7VXVNPaSw0++xmdDMhIDnhyvGgZZ4LpNq90ocFnnEMYxnLNZ1pGKd8RLpz2qJWdcfP8JJtCeAX6v48DWb9rNoxM/7+iLaE9DVX0N7fx3gWuTZprXfh7f1TGi+Qcx683bHRH4IcCpwqCVukEsRK+kiVRZ5KrFuO9WWe4z9XgwvHrStE7gAABsLSURBVHmBuxmmuuMSH8lp8PAnfFEc4opcT1d/DWeuw/l7KqjuuKQmgMtUNyBEdYrH6hIP2mqYfvAaYx2FoU1E8prMuH8cLuKQu64VSJ24GRZ5GhpKpIRIJ5TxfH87IdfdKoPwgwdfUaGVe+C+yiFq3+2gq7+G2+9MQZRKxNHwmkDbeJaz4xiRS3Ksk1PZgY/jYgYnUY2QKWYczR3G28knv3DdKWklS5ErjmG87pcIlowpFZs+wA+dizz8pnQ+/Fd9mT7LjWAcuXY9vGqeS/rYJz7hlmhRcxSr4e9XCWSPHhpqLmqWUfLHHZNDIp6r0Rfp8JMbt1xhPP506z43YoYJvfXBXaIH8WUZksIdaEzhV+3qHgImTRqh5cLTSX0Tl/GhHYI/vx82/kQ/iW5GXVFVRfqEdf/nj/imCoeUor1HwlMJfCKXXCtm0hX14VQ3SzQS/S2s+zxCyVwzZTbvVwWfl/h6mclVlglvgmNxSRWLZC2eXZ1M33SNgQfLTQXczKGzZlLlSsnWBH0i5HUp2ly0yCF90R25bJ3HSwSL3MCu2YXJlRJ43dSWbuBCOVeZGSh9qr2Z6HdwGS+t+Hhp01YGOspDT7oBctVgyxw5MLEZiVyOXEl3RcRoOM1qT+S3iDLZCfYNmo1ORFaBKAb5bwJNt3PO6jeX8ZFI9chyuZrmC0/DIJR4ehmoLDcVcEsnuWCFx0/clrgQYpIQ4qwQ4r/rz2cKIc4IIXqEEK1CiD/VX79Df35Zf/+B9AwdctciN8iGf++jKLdsEu9vYbfPLRZ5NIxJtCq4Oj/OTbrExV2yMZBGHw+94lBgvmKgsTwYelgMiRQ+y/6xm10Scad8G/jA9PxHwI+llBXATWCt/vpa4KaUcjbwY325NOIKeerItrDH62JJQMgtot6kCfBCydxepn+Wo95Eh9KKjy4WxL18SPMOuybdLnER11EshLgP+L/QA7iEEAJYjKrgAfAzYLn++DH9Ofr7j+jLp5FcjVwxyEQmZLJkQ9hT8FtYLfJi+PujgkWylt1VgjNiRtyX/W4T5tg0d0s6L3hoxRf3Z3rFIeQXBf6mhaoWPqgrpSpUq8HiRKxxp5B5HYrXFPkJ8CxgHPXTgGEp5R/15x8B9+qP7wU+BNDf/4O+fAhCiKeEEF1CiK7U1QfOZSEH5wq5lUyIeazfIoY1bmUQ/kKTnBadNO6EmQk4wDt6a6MW15qozJdLg0/0Jt2X1lSjJfDbHqhezTreUBZ4pbqNviuoPdKhRxKlWshz5T8WPzFFXAjxV8ANKeV75pdtFpVxvBd8Qco3pJQ1Usqa1O6ofBDyXDnQ0i3myQh5FPpUB3VtM2ysjj/Z5wqz2HGwMVD72kXRio/mbkmzXwYifsRjEi2BuYY62hnmbvWkDPDC66PQ2eBJw4jzk3iOyq8CXxdC/A44jHKj/AQoEkIY0S33AR/rjz8C7gfQ3/8i8EkKxxwHue5egdwU83QIeqK/QfSruraOFTR3S45Sj3Y99tq01fDkx4d4pn8b2+4cCzQzmKiYG2/MEWtpqhIquUq3xJtWiUCRsU55LLCs8doluR/tlPpd75KN7GE9G8UMan0dvN1UxzLfcZp3ysD6FNGi0BI55vIrKsUgpohLKbdKKe+TUj4ArALekVL+38BplOcK4BvAz/XHv9Cfo7//jsxaRlGuCznkjpAbZFrIY+xjI60bQuLEZ3IVHoOHYmxZOwQL7/EzdrGQ5m7J1zgZ76Dzkr1sCBHy5p0yWIVwEJo3SO67MMQznxXQdmEF30CFHbZTx7OFcKjjSRYu9sOv4CRL2MBenvmsgKW08wov0Na6IkNhhvnDeK4PnwOeFkJcRvm89+uv7wem6a8/DTw/viGOl3wR8lwScweELFqjHIyMzUFY5jmusjT7CZSstcOwHq8yUwlVNxwXM8KW0yZA93XtOuyW1xjoKGeSeJVmv+5GMSVPBUodaDDltdvQDd+V+xm+o4jXeI7C/Wr5BbzHpHdHaNu1gvt2DTHl7du04mMB7/G2r06l4ldhn4XrEkaOpt0nS64mB1nJcpPmhElVglG0723et5ODPUj9qMSeAoG4IQPp9kdowPNwJ1qX+sQ3gD+VU7l31ydoegPqcrmatRcOBmuxoNbVtFmgnYVJXxphWukQr/G8innOc7SzIH4tg5ayEdfdZ1mwDKiEAm2UF0p/yEx+x/O8xkBreTCezaAYWAUVnvP0NM9T66oiUA+HMkAz2g5CqDGT766UvE67T5Z8sMoht6xySJ1VnuD33gwlm3qRXxZcb5jK25vqoEyl2z/L64HDQauB03I169jHmk37A+6Co9RTUDwaFBTdGm/WJOLXkjF/ITO5aivgiURoOIlFsta2wuOzhYROWJpLG9hRBr7SVvaygbUXDjLQrAt4hPIIp1ms1nURtdxh1MnTO95vlP9MMBGH/BLyXBLzdLtYbPZrHyzhJOLXkh/yXVrxUevpoGRuLy/wCjynJup+/u5SfJ+3cplZdLEg0HC5Vqzk9sNT1LosFRONx5GKZ+2obsypLkJGuOBJHuEo9TxbGPq+HCoImagM/A7GY+vv44VZXGZgUTkVc88HJz8t5YENF8wP+a6yuvUTZcA1swGc39k+u5oywdwpVvLFvQITy8US6bvauFSMyoVVgBde9LxAPUeZ93APj757jPb+OsYGCwPC4d+0kMX977Ct9Bm2NO4OtRgNjPWuUjU/lnCSOWJt4G3tfljY66erv4ZppUNsNPnRteug3UtW0Wpg9FfhNU5e7hthzF8IZdDkFSo2/r+o8T7zWQENdxzhVZ7nLdFDs1eGT0AmknVpLONVtwrfeXoa5plcV+Yoo0giHq9RkIuuFHDdKXGRL1Y55KZlnixJfE/d+nuPGt4SPVABQ0YOmt6wl27wNp5hTCtkS/PuUMvSaj3qQndGzGAWl9HOBkOytA+hs8PDmL+Qof5pgfRybSnsuKcxxF2RjZDFq10w/47fqFA/06TsS2VT1O/gR01a/grm3HMOgMKvj/HL76ykuvUSzZoMdaNYT3RWy9zOhaLfL2s5ToXvPGtEdYSa4k4X8OwzwUUc8kvIIbfEPEMRLMVQ0XIe+ReCIobplMd49OAxXudZJVzmCofGZbyf4OW/GeN5t+rZuU1uV+6XX8MtWcEluZ+X+0ZCWo/1ikM8BGgn4DWe5ySPBFa3ldeA0PjrRbKWdXKqEtnm4MkhGlpz0A+/SNYGXjdOGM98VhB4/DOgp2MeCxf7A5O4d8lGdUIxTlZ+EP+vZDZX1PpPAN+E7b6N6rcx/16JYhLytkUr6Nk1j+ZuG8s+J/6b2R/jBHenWMkn94pBrrhZknGvWL+baf8VTw5MitUe6WAaQ7R1rAA/7G9aw1HqaetYgXxF0NFei3fXmeClvNnitsPUUqxg5yjbSp/hlmgJJK/4aOUHja8EFm/ao66IO+Ux2natUK9tVkkx93UMBdZZUDzKrNLLzOYKSzjJLdGS8C+inYJHFx/jMrO40j+bsYu6c1uP9GjyChXbPQhUwn7fGq7ygAobrJfB71wJ8reC6+1Tmc9ZZnKVM+944Rcg2qWNmymR0hmmDO1KAq6ugIjvMdbndCs83QIenzvFFfEw8lHIITfEPFVCPlmJw2agGJb5jtPWvCIQbliwc5SxPYWBCTi/byF7Wc+hxieDVmYsC1MX8t/6BbP7Rqgp7eImRfRcmAc7LZ/3Eqx1bghVmWk9ppNC7dwOltIemFxNloPynBqLuRmx+QRlUEVorLfxvlGytxgaW3bQ0vp0MLokpMFxsnWPdCE3zVu8faSO5Yva9X1w1bSsK+LRyOGmEOnC2DH5JuY3cL6Qf0TKYsp1665x7g5aGp4O8W2P+QtDhMs7eCbUH2vx24ZgbjpRBv8olzLWWEjnoEdN0G06T8/gvNDPHsV+sq+MkEYWBcWjKRHwJYB2rprp1dcY6C4PjteIqjHjx17cDbdKmYpYKfH1MqCVWyzw8RSuMzXzACiG5Q3tKsfbb17OqQLuHFxLPCb5JuYGThb0RIXcxho3lzE1W5sGxab36lHW8lGUFQ3xWeLRnlux9vs07vXEmKZVgktyf0iUSyp4uW+EsaOFQQsa7GO8o7iOln1wnLYHV8Qp4LGsU8v/qXiy2geVmNwoxnrshNgpIp4JX7jrTkkh+SrkkD9iHsk/HqNCZjFBd4dV6OMhlnib37dr3KxX7mvypqfkfqc8puqR6NE3cQu46QohdJlkxduKvn+KJ4MGH22axn3iQ6LHhDtFwMEVcesgHC/iBvks5uBMQR+PkEPsfWYV+XhdBFFODnbCbrxm9oVXQcGGURUhg4ov1z6Mc/NxsgT486XwaPsx2hpWhIu4NTQwIna/SyqEzLx/XAEPxY0TTwPZDydKL070I463Pka/5WblU8stXqIsb5cgFCFN3RBwSL2AA9yWtRw7Ab88tzL85BJTwKP9Lqn6L1j3zXgEfGLiinjCTAQhd5qYJ5KyH2v80QQ9GWKIeRyE9JpMMadFJ1vlOcQf9Ctuu6uEiAJuRzpq9d8g8n5zUpErcOL/3xXxpMiHphOxcKqYx0s847da6ZFu8RBBzKPFmgPNhyVd1KCdinMzSbBGVPO2p05Fzxw5H2PpaJZ3vL/FjQRvkXAFPB5cER8XrphnnkQLaaVi7ImIegyXjBF/rd9v921kd90WtEeif2w8aDvhAa5S6+tQseNm4krYSVS8U4HTBNy5uHHiKaGf/J/0NP4oTpz8jIX5T56K8cfKJbDEQFsiPUqO9DLUP42xwUJuiRa0FIwoEuvkVA5Qx17W887ni5kyeFuNJVIJ2TDiEfBUiqjr/04U1xJPGRPBKof4LoMzQbKlbRO5nI9FtP0dwbXSBwMN5dx+dQrn5s7hhtyOdj9pK1t778Of0EUNnR0epvyD6rZjdDiKOd6Yx3OqLe9k92cmcO5/2xXxlOPcnZ16clnMzYzne0Q7eZuE0RIJIh6X/IjnqaOdOb3nuPdcenqJv/TuVo5SHyhqhZ9gR56oxCPgqWA8+y/bx54zcEU8LUwkIQdn/JlScRk+Hus8sX1e4TnPc7zG8o52rvTPRpufnm5AT4pXufH9GZT4eoMulJiulEwIuAP6sMaNs//Prk88beRrDZZIpNrvnAyGKKSi/kqq5gBs/ONAT8M8qosvQRnM8lzmLtmI9v+3d/YxUlVnHH5eP9Ci4iKLW1rkqyx+QLsLsX7ERkARC2nUGsiyaVITaazLkmggNkubVGjTREk1pAERbWlsUmALBTW2FEVcY5sURNnV3SrMogSp8rHoirVJ08rbP865M3dmZ3Znd2bnnjt7nuRm7z1zZ+9v5t75zZn3nvO+A8ha2BfPADwMJz8ez5T1rabwQjDhaEA5UAox8IjK9BWE2wYOvideAoZKrDxM1GGWYvbw+vNa+nGeQ1VwDm2tHVDa2d5Y+UBo/Z/QtqaaRHNN+nT/rPT2GoaagccDb+IlY6gZOZSPkUPRjDwjl8roxqMsWdizMHGhbFxTn5xEtOQrj1HzswQtddcnszu2vHJ9P4sQD/Rcxilskkk8PrM+d0okDJUQSyZRhVmKlN42SV+vI/P82nDKVXYzGCtuDVUvFdpqq5n8n8OcvPCsCYEUwHe1mtvYzRIZbyrmdME5V33OD6s2sJtbuZ8NLF9oy8+1QHrmwGwMxMCj+hItJlGbuM+d4jBRXxxREVXPvNi9wXxmgmYQhDAWkQppAK0zp7ByOuyQBLdcsIczWs1ObWGENvRb1cp6M1TxM0lwqmMcq7Zosszc16o62cYCEq/WmALQ7WQph5YNb+Cu4008MuJzkRSXKOPlpTTyDCoxJc8+EZO/3PbGazsOsVNb+Pnxf7GvYyYzThxgX8dMmqlLPjVczDgX03UuGzfVM5s9XKLV6NOSln428WoNTTySKgKRLUlXwcQ5dBJffDjFCYZqeCUgzmGW3rSHcmavhYa6x1m/ahlUQmvjFDZwP91UsOmbi5Ffairft81x/uzU23mI1TTxKLuZwxx2c1Q29zjK14EVQTm2LtAvBHkto/CwLRZ9PxtY3vGE+SJ5F3KHUvrzJTVYxh3Vl70rHSxfni1GDLXhiJlEVTquGOXg8tDeBSyF9dOWJet81lYeSlYcqni9m2e5nbtadiXHcM+bup3TjCLRUcNiNlE91YwrP5rl378NTOYwBybP4OKWL5AuzVngYnnDE+ZXwEpMaKdgvIFHjTdxpxgKOVhyEVVulmKMLc9l5MH5/Dd0DU8fDRL0uKfBZDq5a92uVA3MLtjZcDc7p91t9q2EkVO72SGJnAomcCS1EZ7ME5rgk7jaJr+aBWzJ1DkQfOjEBbyJO4fvlRviZub5GDkkR6q0k6zss3zVEz17zkHM2hr9J1RwUh/jclme9ejdVDCi+0x6IedshZEhVbU+5ySffHrB5dYDhzj2wsHf2HSYeF5QxSOqG6CFmFMuveFzGTLO43C266LkCJJkhfks0+IPn5gMpE/iAXPTc4Q2MEUW8+OqX3CsbhQszSKhK2MpKBZejgYeX/yNTecZqj3yMHG78ZlLb/hcDk8bapjWYw7apsGxraOYzgEq+IStLORRmtJucE7XuTzEahIdNehIQRIKa0nv2feaM7y/Jl6uBu5ip8nf2CwThnp4BeIXYukrtALJOHlmuCNIE2uNfOyq01AJExvfp/bVQ6aXXgfoHJbIYu5lNd2MhG0glUpD4+Os37Is9f9yGng204rCwKM2b3DTwPPHm3hsGMo3PQOiNPNBMnIgawGJLtKHHDamtjc338s5sz6nTps5fGIyZ1suMubeDutbluUYA95Xkitv4HHFx8RjxVBMppWNKOLlA5nIkk+MHHrUtQyHQaw575s908TObbx8VNVp7lz3ItdW7Wde3fb0ePfxjP/T5/GHqoGXB3mZuIgcEZG3RaRVRPbbtstE5CURSdi/I227iMivRKRTRN4SkRmD+QKGJt7IDXG48ZmvkUNOI4e04YdB28ql8D4TWcC21POyjkjpT6rZUuCKgZfH56g/PfHZqlqrqtfa7SbgZVWtBl622wDzgGq73AcUP0myB98rD4iqV14M8jx/mUMP2+FU8zhWtSunOsaxeN2m4h8zSTnkQclG+Xx2Cgmn3AnJhGvPAHeF2n+nhr8DFSIypoDjeHqlfC7GwnA5vNKbtmyhFUtmjzocJmkhNa0+vF+QIRHS094OSFtUedkHm/L6zORr4gq8KCJviEgwFrBKVT8CsH+DuzhfBT4IPfeYbUtDRO4Tkf0mPOPaz7244XvlBpeMIpP+6Mrj8/Bls8ybut3MwAwPV+zB8FwPlAhXz0l5kO/olJtU9UMRuRx4SUR6K7WabVxjj8HoqvoU8BQE48Q9heNHsBhKmYulGPlX8jxvQTWeSnhvpfAmsGCtUt3YRgIzpX70zKOcmj3O7NdnlsJS9MJdM/Dy6+zkZeKq+qH9e1JEdgDXASdEZIyqfmTDJcHZOgZcEXr6WODDImr29IofV24o5XDEfMeTF/jlUonJPghMXAiTXjP5whMtNcne+FYWMuuqvWa/dkLV7YdT2l+8rpk3lKOBQx7hFBG5SEQuCdaBuZjL43ngHrvbPcBzdv154Pt2lMoNwKdB2MVTSsrzgu0/rplJf0arZGEazKvbzpRbWlPjyLsw+VC2wax1e2EpPLxUzPT7J8kzNh6m0F64a+85lPPnIZ+YeBXwVxFpA/YBf1LVvwCPALeJSAK4zW4D/Bl4D+gEngaWFF21J0/K98LtH6WKlRfjRmcvVEL91I1M4AiJhprUmPBg6YL6xo2wFjZpqzH2teSIl+fSUI4GXt44kjtFPgMORq0jT4L5dK4TF50QH61x0Qnx0RoXnVB6reNVdXRfO7ky7f5gaPy504jI/jhojYtOiI/WuOiE+GiNi05wV6ufdu/xeDwxxpu4x+PxxBhXTPypqAX0g7hojYtOiI/WuOiE+GiNi05wVKsTNzY9Ho/HMzBc6Yl7PB6PZwBEbuIi8m0ROWhT1zb1/YxB1bJRRE6KSHuozcmUuyJyhYi8IiLviEiHiDzgol4RuVBE9olIm9W5yrZPFJG9VmeziAyz7RfY7U77+IRS6AzpPVdEDojIC47rjEV6aBGpEJFtIvKuvVZvdFTnlfa9DJYzIvKgi1p7oKqRLcC5wGFgEjAMaAOuiVDPzcAMoD3UthposutNwKN2fT6wE5Mr5gZgb4m1jgFm2PVLgEPANa7ptce72K6fD+y1x/8DsMi2Pwk02PUlwJN2fRHQXOL3dRmwCXjBbruq8whQmdHm1Lm3x34G+IFdHwZUuKgzQ/O5mOlT413XqqqRm/iNwK7Q9gpgRcSaJmSY+EFgjF0fgxnTDrABqM+2X0S6n8PMnHVWLyaBx5vA9ZhJE+dlXgfALuBGu36e3U9KpG8sJjf+LcAL9gPqnE57zGwm7tS5B0YA72e+L67pzKJ7LvC3OGhV1cjDKXmlrY2YglLulgL7U346ppfrnF4bomjFzMl+CfPrq1tV/5dFS1KnffxTYFQpdAJrgB8BZ+32KEd1wiCkhx4EJgGngN/aENWvxeRfck1nJouAzXbdda2Rm3heaWsdxQntInIx8EfgQVU909uuWdpKoldVv1DVWkxP9zrg6l60RKJTRL4DnFTVN8LNvWiJ+vzfpKozMJW0GkXk5l72jUrreZjw5HpVnQ58TqoCWDaifk+x9zzuALb2tWuWtki8K2oTj0Pa2hNiKxOJYyl3ReR8jIH/XlW322Zn9apqNyY56g2Yik9B2oewlqRO+/ilwMclkHcTcIeIHAG2YEIqaxzUCaSnhwbS0kNbTS6c+2PAMVXda7e3YUzdNZ1h5gFvqmqQPc5lrUD0Jv46UG1HAAzD/Ix5PmJNmTiZcldEBPgN8I6qPu6qXhEZLSIVdv1LwBzgHeAVktmxe+gM9C8A9qgNOg4mqrpCVceq6gTMdbhHVb/nmk6IT3poVT0OfCAiV9qmW4F/uKYzg3pSoZRAk6taDVEE4jNuIszHjKw4DPwkYi2bgY+A/2K+aRdj4pwvAwn79zK7rwDrrO63gWtLrPVbmJ9vbwGtdpnvml7gG8ABq7Md+Kltn4RJbdyJ+el6gW2/0G532scnRXAdzCI1OsU5nVZTm106gs+Na+feHrsW2G/P/7PASBd12uMPB04Dl4banNQaXvyMTY/H44kxUYdTPB6Px1MA3sQ9Ho8nxngT93g8nhjjTdzj8XhijDdxj8fjiTHexD0ejyfGeBP3eDyeGONN3OPxeGLM/wFdYitaUt9g1wAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%time\n", "\n", "h, w = 2048//4, 3072//4\n", "gimage = np.zeros((h, w), dtype=np.uint8)\n", "xmin, xmax, ymin, ymax = np.array([-2.0, 1.0, -1.0, 1.0]).astype('float32')\n", "iters = 50\n", "create_fractal(xmin, xmax, ymin, ymax, gimage, iters)\n", "plt.imshow(gimage, cmap='jet')\n", "pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parallelism with `multiprocessing`" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import multiprocessing" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def mandel(x, y, max_iters):\n", " c = complex(x, y)\n", " z = 0.0j\n", " for i in range(max_iters):\n", " z = z*z + c\n", " if abs(z) >= 4:\n", " return i\n", " return max_iters\n", "\n", "def create_fractal(xmin, xmax, ymin, ymax, image, iters):\n", " height, width = image.shape\n", "\n", " pixel_size_x = (xmax - xmin)/width\n", " pixel_size_y = (ymax - ymin)/height\n", "\n", " args = [] \n", " for x in range(width):\n", " real = xmin + x*pixel_size_x\n", " for y in range(height):\n", " imag = ymin + y*pixel_size_y\n", " args.append((real, imag, iters))\n", " \n", " p = multiprocessing.Pool()\n", " colors = np.array(p.starmap(mandel, args), 'float')\n", " p.close()\n", " \n", " return colors.reshape((width, height)).T" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 2.3 s, sys: 180 ms, total: 2.48 s\n", "Wall time: 2.53 s\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%time\n", "\n", "h, w = 2048//4, 3072//4\n", "gimage = np.zeros((h, w), dtype=np.uint8)\n", "xmin, xmax, ymin, ymax = np.array([-2.0, 1.0, -1.0, 1.0]).astype('float32')\n", "iters = 50\n", "gimage = create_fractal(xmin, xmax, ymin, ymax, gimage, iters)\n", "plt.imshow(gimage, cmap='jet')\n", "pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parallelism in `numba`" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "from numba import jit, prange" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### JIT with `numba`" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "@jit(nopython=True, cache=True)\n", "def mandel(x, y, max_iters):\n", " c = complex(x, y)\n", " z = 0\n", " for i in range(max_iters):\n", " z = z*z + c\n", " if abs(z) >= 4:\n", " return i\n", " return max_iters" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "@jit(nopython=True, cache=True)\n", "def create_fractal(xmin, xmax, ymin, ymax, image, iters):\n", " height, width = image.shape\n", "\n", " pixel_size_x = (xmax - xmin)/width\n", " pixel_size_y = (ymax - ymin)/height\n", "\n", " for x in range(width):\n", " real = xmin + x*pixel_size_x\n", " for y in range(height):\n", " imag = ymin + y*pixel_size_y\n", " color = mandel(real, imag, iters)\n", " image[y, x] = color" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 2.16 s, sys: 28 ms, total: 2.19 s\n", "Wall time: 2.19 s\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%time\n", "\n", "h, w = 2048, 3072\n", "gimage = np.zeros((h, w), dtype=np.uint8)\n", "xmin, xmax, ymin, ymax = np.array([-2.0, 1.0, -1.0, 1.0]).astype('float32')\n", "iters = 50\n", "create_fractal(xmin, xmax, ymin, ymax, gimage, iters)\n", "plt.imshow(gimage, cmap='jet')\n", "pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### JIT with `numba` and `prange` using `parallel` option" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# function to be run in parallel needs `nogil=True`\n", "@jit(nopython=True, nogil=True)\n", "def mandel(x, y, max_iters):\n", " c = complex(x, y)\n", " z = 0.0j\n", " for i in range(max_iters):\n", " z = z*z + c\n", " if abs(z) >= 4:\n", " return i\n", " return max_iters\n", "\n", "@jit(nopython=True, parallel=True)\n", "def create_fractal(xmin, xmax, ymin, ymax, image, iters):\n", " height, width = image.shape\n", "\n", " pixel_size_x = (xmax - xmin)/width\n", " pixel_size_y = (ymax - ymin)/height\n", "\n", " # replace `range` with `prange`\n", " for x in prange(width):\n", " real = xmin + x*pixel_size_x\n", " for y in prange(height):\n", " imag = ymin + y*pixel_size_y\n", " color = mandel(real, imag, iters)\n", " image[y, x] = color" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 2.44 s, sys: 4 ms, total: 2.44 s\n", "Wall time: 1.06 s\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%time\n", "\n", "h, w = 2048, 3072\n", "gimage = np.zeros((h, w), dtype=np.uint8)\n", "xmin, xmax, ymin, ymax = np.array([-2.0, 1.0, -1.0, 1.0]).astype('float32')\n", "iters = 50\n", "create_fractal(xmin, xmax, ymin, ymax, gimage, iters)\n", "plt.imshow(gimage, cmap='jet')\n", "pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parallelism in `cython`" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import cython" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "%load_ext cython" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_a3593081874235a8f98aec77c6842da6.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.27.3

\n", "

\n", " Yellow lines hint at Python interaction.
\n", " Click on a line that starts with a \"+\" to see the C code that Cython generated for it.\n", "

\n", "
 01: 
\n", "
+02: cimport cython
\n", "
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 03: 
\n", "
 04: cdef extern from "complex.h":
\n", "
 05:     double cabs(double complex)
\n", "
 06: 
\n", "
+07: cdef unsigned char mandel_cython(double x, double y, int max_iters):
\n", "
static unsigned char __pyx_f_46_cython_magic_a3593081874235a8f98aec77c6842da6_mandel_cython(double __pyx_v_x, double __pyx_v_y, int __pyx_v_max_iters) {\n",
       "  __pyx_t_double_complex __pyx_v_c;\n",
       "  __pyx_t_double_complex __pyx_v_z;\n",
       "  int __pyx_v_i;\n",
       "  unsigned char __pyx_r;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"mandel_cython\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L0:;\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "
 08:     cdef double complex c, z
\n", "
 09: 
\n", "
+10:     c = x + y*1j
\n", "
  __pyx_v_c = __Pyx_c_sum_double(__pyx_t_double_complex_from_parts(__pyx_v_x, 0), __Pyx_c_prod_double(__pyx_t_double_complex_from_parts(__pyx_v_y, 0), __pyx_t_double_complex_from_parts(0, 1.0)));\n",
       "
+11:     z = 0.0j
\n", "
  __pyx_v_z = __pyx_t_double_complex_from_parts(0, 0.0);\n",
       "
+12:     for i in range(max_iters):
\n", "
  __pyx_t_1 = __pyx_v_max_iters;\n",
       "  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {\n",
       "    __pyx_v_i = __pyx_t_2;\n",
       "
+13:         z = z*z + c
\n", "
    __pyx_v_z = __Pyx_c_sum_double(__Pyx_c_prod_double(__pyx_v_z, __pyx_v_z), __pyx_v_c);\n",
       "
+14:         if cabs(z) >= 2:
\n", "
    __pyx_t_3 = ((cabs(__pyx_v_z) >= 2.0) != 0);\n",
       "    if (__pyx_t_3) {\n",
       "/* … */\n",
       "    }\n",
       "  }\n",
       "
+15:             return i
\n", "
      __pyx_r = __pyx_v_i;\n",
       "      goto __pyx_L0;\n",
       "
+16:     return max_iters
\n", "
  __pyx_r = __pyx_v_max_iters;\n",
       "  goto __pyx_L0;\n",
       "
 17: 
\n", "
 18: @cython.cdivision(True)
\n", "
+19: def create_fractal_cython(double xmin, double xmax, double ymin, double ymax,
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_a3593081874235a8f98aec77c6842da6_1create_fractal_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_a3593081874235a8f98aec77c6842da6_1create_fractal_cython = {\"create_fractal_cython\", (PyCFunction)__pyx_pw_46_cython_magic_a3593081874235a8f98aec77c6842da6_1create_fractal_cython, METH_VARARGS|METH_KEYWORDS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_a3593081874235a8f98aec77c6842da6_1create_fractal_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
       "  double __pyx_v_xmin;\n",
       "  double __pyx_v_xmax;\n",
       "  double __pyx_v_ymin;\n",
       "  double __pyx_v_ymax;\n",
       "  __Pyx_memviewslice __pyx_v_image = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  int __pyx_v_iters;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"create_fractal_cython (wrapper)\", 0);\n",
       "  {\n",
       "    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_xmin,&__pyx_n_s_xmax,&__pyx_n_s_ymin,&__pyx_n_s_ymax,&__pyx_n_s_image,&__pyx_n_s_iters,0};\n",
       "    PyObject* values[6] = {0,0,0,0,0,0};\n",
       "    if (unlikely(__pyx_kwds)) {\n",
       "      Py_ssize_t kw_args;\n",
       "      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);\n",
       "      switch (pos_args) {\n",
       "        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  0: break;\n",
       "        default: goto __pyx_L5_argtuple_error;\n",
       "      }\n",
       "      kw_args = PyDict_Size(__pyx_kwds);\n",
       "      switch (pos_args) {\n",
       "        case  0:\n",
       "        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_xmin)) != 0)) kw_args--;\n",
       "        else goto __pyx_L5_argtuple_error;\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  1:\n",
       "        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_xmax)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 1); __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "        }\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  2:\n",
       "        if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_ymin)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 2); __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "        }\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  3:\n",
       "        if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_ymax)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 3); __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "        }\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  4:\n",
       "        if (likely((values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_image)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 4); __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "        }\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  5:\n",
       "        if (likely((values[5] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_iters)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 5); __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "        }\n",
       "      }\n",
       "      if (unlikely(kw_args > 0)) {\n",
       "        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"create_fractal_cython\") < 0)) __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "      }\n",
       "    } else if (PyTuple_GET_SIZE(__pyx_args) != 6) {\n",
       "      goto __pyx_L5_argtuple_error;\n",
       "    } else {\n",
       "      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
       "      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
       "      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
       "      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n",
       "      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);\n",
       "      values[5] = PyTuple_GET_ITEM(__pyx_args, 5);\n",
       "    }\n",
       "    __pyx_v_xmin = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_xmin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "    __pyx_v_xmax = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_xmax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "    __pyx_v_ymin = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_ymin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "    __pyx_v_ymax = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_ymax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "    __pyx_v_image = __Pyx_PyObject_to_MemoryviewSlice_dsds_unsigned_char(values[4]); if (unlikely(!__pyx_v_image.memview)) __PYX_ERR(0, 20, __pyx_L3_error)\n",
       "    __pyx_v_iters = __Pyx_PyInt_As_int(values[5]); if (unlikely((__pyx_v_iters == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 20, __pyx_L3_error)\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L5_argtuple_error:;\n",
       "  __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 19, __pyx_L3_error)\n",
       "  __pyx_L3_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_a3593081874235a8f98aec77c6842da6.create_fractal_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_a3593081874235a8f98aec77c6842da6_create_fractal_cython(__pyx_self, __pyx_v_xmin, __pyx_v_xmax, __pyx_v_ymin, __pyx_v_ymax, __pyx_v_image, __pyx_v_iters);\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_a3593081874235a8f98aec77c6842da6_create_fractal_cython(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_xmin, double __pyx_v_xmax, double __pyx_v_ymin, double __pyx_v_ymax, __Pyx_memviewslice __pyx_v_image, int __pyx_v_iters) {\n",
       "  int __pyx_v_x;\n",
       "  int __pyx_v_y;\n",
       "  int __pyx_v_height;\n",
       "  int __pyx_v_width;\n",
       "  double __pyx_v_pixel_size_x;\n",
       "  double __pyx_v_pixel_size_y;\n",
       "  double __pyx_v_real;\n",
       "  double __pyx_v_imag;\n",
       "  unsigned char __pyx_v_color;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"create_fractal_cython\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_r = Py_None; __Pyx_INCREF(Py_None);\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_a3593081874235a8f98aec77c6842da6.create_fractal_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_v_image, 1);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__20 = PyTuple_Pack(15, __pyx_n_s_xmin, __pyx_n_s_xmax, __pyx_n_s_ymin, __pyx_n_s_ymax, __pyx_n_s_image, __pyx_n_s_iters, __pyx_n_s_x, __pyx_n_s_y, __pyx_n_s_height, __pyx_n_s_width, __pyx_n_s_pixel_size_x, __pyx_n_s_pixel_size_y, __pyx_n_s_real, __pyx_n_s_imag, __pyx_n_s_color); if (unlikely(!__pyx_tuple__20)) __PYX_ERR(0, 19, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__20);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__20);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_a3593081874235a8f98aec77c6842da6_1create_fractal_cython, NULL, __pyx_n_s_cython_magic_a3593081874235a8f9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 19, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_create_fractal_cython, __pyx_t_1) < 0) __PYX_ERR(0, 19, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_codeobj__21 = (PyObject*)__Pyx_PyCode_New(6, 0, 15, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__20, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_jovyan_cache_ipython_cytho, __pyx_n_s_create_fractal_cython, 19, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__21)) __PYX_ERR(0, 19, __pyx_L1_error)\n",
       "
 20:                           unsigned char[:, :] image, int iters):
\n", "
 21: 
\n", "
 22:     cdef int x, y
\n", "
 23:     cdef int height, width
\n", "
 24:     cdef double pixel_size_x, pixel_size_y
\n", "
 25:     cdef double real, imag
\n", "
 26:     cdef unsigned char color
\n", "
 27: 
\n", "
+28:     height = image.shape[0]
\n", "
  __pyx_v_height = (__pyx_v_image.shape[0]);\n",
       "
+29:     width = image.shape[1]
\n", "
  __pyx_v_width = (__pyx_v_image.shape[1]);\n",
       "
 30: 
\n", "
+31:     pixel_size_x = (xmax - xmin)/width
\n", "
  __pyx_v_pixel_size_x = ((__pyx_v_xmax - __pyx_v_xmin) / ((double)__pyx_v_width));\n",
       "
+32:     pixel_size_y = (ymax - ymin)/height
\n", "
  __pyx_v_pixel_size_y = ((__pyx_v_ymax - __pyx_v_ymin) / ((double)__pyx_v_height));\n",
       "
 33: 
\n", "
+34:     for x in range(width):
\n", "
  __pyx_t_1 = __pyx_v_width;\n",
       "  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {\n",
       "    __pyx_v_x = __pyx_t_2;\n",
       "
+35:         real = xmin + x*pixel_size_x
\n", "
    __pyx_v_real = (__pyx_v_xmin + (__pyx_v_x * __pyx_v_pixel_size_x));\n",
       "
+36:         for y in range(height):
\n", "
    __pyx_t_3 = __pyx_v_height;\n",
       "    for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {\n",
       "      __pyx_v_y = __pyx_t_4;\n",
       "
+37:             imag = ymin + y*pixel_size_y
\n", "
      __pyx_v_imag = (__pyx_v_ymin + (__pyx_v_y * __pyx_v_pixel_size_y));\n",
       "
+38:             color = mandel_cython(real, imag, iters)
\n", "
      __pyx_v_color = __pyx_f_46_cython_magic_a3593081874235a8f98aec77c6842da6_mandel_cython(__pyx_v_real, __pyx_v_imag, __pyx_v_iters);\n",
       "
+39:             image[y, x]  = color
\n", "
      __pyx_t_5 = __pyx_v_y;\n",
       "      __pyx_t_6 = __pyx_v_x;\n",
       "      __pyx_t_7 = -1;\n",
       "      if (__pyx_t_5 < 0) {\n",
       "        __pyx_t_5 += __pyx_v_image.shape[0];\n",
       "        if (unlikely(__pyx_t_5 < 0)) __pyx_t_7 = 0;\n",
       "      } else if (unlikely(__pyx_t_5 >= __pyx_v_image.shape[0])) __pyx_t_7 = 0;\n",
       "      if (__pyx_t_6 < 0) {\n",
       "        __pyx_t_6 += __pyx_v_image.shape[1];\n",
       "        if (unlikely(__pyx_t_6 < 0)) __pyx_t_7 = 1;\n",
       "      } else if (unlikely(__pyx_t_6 >= __pyx_v_image.shape[1])) __pyx_t_7 = 1;\n",
       "      if (unlikely(__pyx_t_7 != -1)) {\n",
       "        __Pyx_RaiseBufferIndexError(__pyx_t_7);\n",
       "        __PYX_ERR(0, 39, __pyx_L1_error)\n",
       "      }\n",
       "      *((unsigned char *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_image.data + __pyx_t_5 * __pyx_v_image.strides[0]) ) + __pyx_t_6 * __pyx_v_image.strides[1]) )) = __pyx_v_color;\n",
       "    }\n",
       "  }\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "cimport cython\n", "\n", "cdef extern from \"complex.h\":\n", " double cabs(double complex)\n", "\n", "cdef unsigned char mandel_cython(double x, double y, int max_iters):\n", " cdef double complex c, z\n", "\n", " c = x + y*1j\n", " z = 0.0j\n", " for i in range(max_iters):\n", " z = z*z + c\n", " if cabs(z) >= 2:\n", " return i\n", " return max_iters\n", "\n", "@cython.cdivision(True)\n", "def create_fractal_cython(double xmin, double xmax, double ymin, double ymax, \n", " unsigned char[:, :] image, int iters):\n", "\n", " cdef int x, y\n", " cdef int height, width\n", " cdef double pixel_size_x, pixel_size_y\n", " cdef double real, imag\n", " cdef unsigned char color\n", "\n", " height = image.shape[0]\n", " width = image.shape[1]\n", " \n", " pixel_size_x = (xmax - xmin)/width\n", " pixel_size_y = (ymax - ymin)/height\n", " \n", " for x in range(width):\n", " real = xmin + x*pixel_size_x\n", " for y in range(height):\n", " imag = ymin + y*pixel_size_y\n", " color = mandel_cython(real, imag, iters)\n", " image[y, x] = color " ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 2.16 s, sys: 16 ms, total: 2.17 s\n", "Wall time: 2.17 s\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%time\n", "\n", "h, w = 2048, 3072\n", "gimage = np.zeros((h, w), dtype=np.uint8)\n", "xmin, xmax, ymin, ymax = np.array([-2.0, 1.0, -1.0, 1.0]).astype('float32')\n", "iters = 50\n", "create_fractal_cython(xmin, xmax, ymin, ymax, gimage, iters)\n", "plt.imshow(gimage, cmap='jet')\n", "pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Parallel version with `cython`" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "%%cython --compile-args=-fopenmp --link-args=-fopenmp --force\n", "\n", "import cython\n", "from cython.parallel import parallel, prange\n", "\n", "# All cdef functions need to be `nogil`\n", "cdef extern from \"complex.h\" nogil:\n", " double cabs(double complex)\n", "\n", "# All cdef functions need to be `nogil`\n", "cdef unsigned char mandel_cython(double x, double y, int max_iters) nogil:\n", " cdef double complex c, z\n", "\n", " c = x + y*1j\n", " z = 0.0j\n", " for i in range(max_iters):\n", " z = z*z + c\n", " if cabs(z) >= 2:\n", " return i\n", " return max_iters\n", "\n", "@cython.cdivision(True)\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def create_fractal_cython_par(double xmin, double xmax, double ymin, double ymax, \n", " unsigned char[:, :] image, int iters):\n", "\n", " cdef int x, y\n", " cdef int height, width\n", " cdef double pixel_size_x, pixel_size_y\n", " cdef double real, imag\n", " cdef unsigned char color\n", "\n", " height = image.shape[0]\n", " width = image.shape[1]\n", " \n", " pixel_size_x = (xmax - xmin)/width\n", " pixel_size_y = (ymax - ymin)/height\n", " \n", " # use prange in parallel, nogil context\n", " with cython.nogil, parallel():\n", " for x in prange(width):\n", " real = xmin + x*pixel_size_x\n", " for y in prange(height):\n", " imag = ymin + y*pixel_size_y\n", " color = mandel_cython(real, imag, iters)\n", " image[y, x] = color " ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 3.11 s, sys: 12 ms, total: 3.12 s\n", "Wall time: 788 ms\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXkAAAD8CAYAAACSCdTiAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAAIABJREFUeJzsvX94VeWZ9/u58e2Z6HFISPLqpraeQJQmGr344fg2JrVReJ3itCRA9DRqrRimEvTqtASGqvRkcxV/MBDs20uJdgg4HpUeCgjawowFTG0iHodfR6PJWAKMoxJ5k5DwetV0WnnOH89ae6+9svbv3zvrc1372nuvH8969t5rf9e97ud+7luUUri4uLi45CYT0t0BFxcXF5fk4Yq8i4uLSw7jiryLi4tLDuOKvIuLi0sO44q8i4uLSw7jiryLi4tLDpNykReRb4jIv4nIcRH5UaqP7+Li4jKekFTGyYvIBcD7wH8HPgT+FWhQSr2Xsk64uLi4jCNSbclfDxxXSp1QSv0n8AugNsV9cHFxcRk3/JcUH+8y4D8s7z8E/pt9IxH5HvA9/e4Ls6A4FX2z8IUUHSfVX/94I1W/Yyhi6YPTeXGBfppg2+QLxus8yPvSH7j6ox4O/2kWjAJ/sm1TAHyqt+XPxrJhY7s/A+c/txzvz5bXfyK5JLP9P4ffJCsZRKlPJZItU60yTp0a4y9SSv0c+DmAyBeVT+9TwqUpOs4lKTrOeCVVv2MoYu2Dfb+J/pcXWRabto8HqIaCdSd4lavZxTQav/WiXjdgbFcMeT8d4rPfFuGthdW7lF63xtjmPwHOWRr/xNYH+/tEk8z2zySx7XTxeMRbplrkPwS+bHn/JeDjFPchzbjinlwyQdzjIcb+G4Jf1PWZX9gByozXZTA6MAnpUdAJbAJ60dt+Gqwfn4R4n2iS2b75n8tFsQ9PqkX+X4ErRWQK8BHwbeCOFPchBMkWCFfgk0smCXyi+jIx/CYAndDfOxXKQJ0UpE5pES+G8sYjnBwpYfTpQi3wnUB3LH3JZqEH/f8bf0KfUpFXSv1ZRB4A/gXtZNyslHo3lX1IH67AJ5dxLPAmA/ohf6Uorz3C8tr17GMOW9feq9eZlnu/ZXtHKz4UrtBnGykf+VNK7QH2pPq44UmmSLgCnzwySdwhvv6E2ffiCJsZgJ6umTTyorbaTXEfiKU/yfbFp+O440vo3RmvSccV+OSRywIfoRXvcVhWDJ6qE+AJMQfGUfAjvXO4lOR/967rNFG4Ig8k74QaPydS6sk0gU8kDmIbiRVvDLC2N97BTXSQV3yWvCVDie6cBVfoswFX5JPG+DiBUk8qrMhYSKKbxoli/FZ8sf/haTzBepYzTRqZn7+L0Y7CwH3sROoCCkouCH1u/1ddkU/4SZT7J036yERxh6S7aexCXGx5LgMW4xP5/t1TfZtt7VsUECcfGfbjR/LZMvV3iYbc/c+6Uy4TSu6eKOknU4Ukkf2yCaxV3K0i7cEf/14M6rgg1QqKoalqA0WGw91TepL+7qmBIt+LP7rGepyoo2zsJHOwNFUDwLk5IDvOLflE/kFdgU8Omeqegfj7Zd3fQeAtbhgfHv+ypnUbUIeFHzc/SGXtATxVJyhigLvlMQB+KaV4ak9ANTSt3ADVtjbsxwvWl6g+T7J+K3cmeqykNAtlLCQ3rUGiTpzcOzEyg0wVd0i8D94QVlNslxjPZvijFVP4y/Qjr2aId/OvZphJzGztwbtcbzZPlfMATwLwxrOzka+dh6dFh1VaY+XtfAqBKQ4geks6WZZ3qkI6M92ifxyl/j0jc9dkEK7AZzbjTODtrpleyHt+iNE1hX6hd/KrGyJ9iim8Lgd52bLqZenhjYdmc+SRci6cPwjdoi8MvcYG/UHaBPh0ImOFPhrSFWOfKHLHdTPO3TXx4gp8chinAm9a6IY7ZbSjkP3rboA6AnzwAS6cGsXzBUW8Lgcdj9j5KDzAk4wOTPJPjDLxEBhn7wFqgApL30L2PRzJcN+k8tzIjf/3OBX5RJwouXECZB7jTOBBC3Y9WmQr0L5zq4VdowJdNNXaH08Z0C88oPqCHnUfUM/2wIX2i0WN8ShDX1DqSEBopRVX6NPJOHbXxEP2//CZSaYKfDJi4A2BLwFqoHLLAQ6uvRmKYVXjQwxSzCXSzM2dwIAEhE1WNh6gnu28VFvHUzzAJhZzt/LwnNjDZqBlEK5msX5TBlQo7Ze3UgaVKw8wm33cRAezH3/D1k/TbROPC8b8HhLlwkmlOyi7XTfjUOTjFRJX4BNPpoo7JC4nfGjeeHk2t67cwZPcT+nu0wA0KZhMHXThj4xBW+avy0EeUat4W/byP9jLcw5teivgSGE5NXRQU9rBluJ7uCm/g71L5vuFvhjU88KGlU00r93IGmuIZUJCK+1kq68+e4V+HEbXuCKfWeSawEeyjy2SphjtpqnDlx4YYMfKW1lw2V4OfFTJnTzPu1xNNV1M5xjTpDHqnrUMgpwBGVQBg7mtjUtp7nsKtotebgp9QJbKUAVFYiUR7aT6gpEpQh95dM0488m7Ap9Z5JLARzrIGCQGvRvYhV9kgYV9v2boozxOUcLpJaUU9o6ynPUxCTzA6iLgfcirGGJ/4w367qAM1rGclismsGrlQzRs2RyYMsGRRP1uiWgn1edQ9mnAOHTXxEr2/biZTaYKfCziHilhJhmZYZJGWGTLFRMofAg+eHQrXoBnwHub8TpGvLUwX+1imAIqqw6wHJ1z/hnVR//uqSgRtv50EdxlNxLtIZWJcrsk2lfvYmccWfLxiIor8IklFwQ+2vDAEAI/4PB6QNdhveORdrwP+Vd7fxnFIYPwwlAjb8te3uidzYKX9zKHfTrnTSfI7xSskbGpDxxJ5O+Y4gRvcZFdejCORD5WsusHzWxyIUVBLJ8hyjQBZiTNAAxTwIFHKqM8XmhWF+lnbzm+8j1NtRv81aN6g+zo+Dlcoc90XJEPSfb8kJlPJot7pJkWY/kMQQQ+VBy6ka6AYtjbN59jTMdbEWL7ODjxtIeFXXtoW7HMXz0qpBWfCqHP1HPFTnboQ8wiLyJfFpHXRKRHRN4Vkb8zlntF5CMROWY8brXs86CIHBeRfxORv07EB4iMWE6a7PgBs4NM/dOG69elxCc6MST6KobWlUtpWSzk1QzhKT3JD4fa8MZUeDtM71QTVXSFsNwJcjEKJvTpturTcZ5lvk7EY8n/GWhWSpUDXwXuF5GrjHVPKKWmG489AMa6bwNXA98ANorIBXEc3yUryESBj0SQ4u13jJkci+EQ1wFwU34Hp28v5WhheZx9cWZZa5t+YcyiDZhpG3U9WJNEin0sbblCbyfm6Bql1GngtPH6f4lID3BZiF1qgV8opf4InBSR48D1gHPSjYThWvHpI9MEPhUFMCIQ9xBFQNq33ME+5vCW2sH/kIU6kkZ64uyTM0eay5nEMFOqDlDCKV78SiPS6zBvxnFSVLgEZomMmsnWCVSZQUJCKEWkBJgB/L9AFfCAiNwNHEJb+2fRF4A3Lbt9SJCLgoh8D98MqPxEdDEKXIFPDNkm8InobwwCb2LEpTeueNHnj78+AT0KxcvSwxq1ilOUcJwrkN3Kb8FbQjmBGIUeAr/XeIQ6GqFPx0Uhc2fExj3wKiIXAzuAHyilzgFtQCkwHW3pt5qbOuzuON1WKfVzpdR1Sqnr4KJ4uxgFrsAnhkwS+HC3/IlwL0wkHvdMAJYIl9XHz3O38uDtjK93oXhb9rKPObR1LWOkRfTxQ06EshPN577U4RENmXReOZGZ+hGXyIvIF9AC/4JSaieAUuoTpdTnSqnzwD/iN0g+BL5s2f1LwMfxHD88mX5S5BqZFBmRTL/7RNsjAi5mbM74YPnhDQta3TiB9axAJcclz/dVHq+q/ezdvQB2QX5DmBQn9s/gI9ZKUuAs/OEuypG2mw4yT+jjia4RoB3oUUptsCyfbNlsPnrCNsDLwLdF5C9EZApwJfBWrMdPPJn342QX2Sbu9m3swh3qESXBfPAmQSznnR/N5amhZl9ce6LZxXzeeHi2zkwJzhWonEi40DsRSvAz5VzLDuLxyVcB3wHeEZFjxrKHgAYRmY52xZwC7gNQSr0rItuA99CROfcrpT6P4/hhiOZEcAU+PjLhTxeLhRdGmJzELJqsjOHEHYK7Rorhfp5kwZZSvFvAuyiK40bI18RIkTBVxgq8B3/lKKdIG/OzBXwf5vcZT0UpJ5wGcSPxu6drwDaz/PM5nIUy0j+9K/DxkW6BjzYVAUQ8QakY2Kd0HhczK2MsBLOI7QJvibKx1nBVtwveBDs271Yevsmv6dk9U1eMsriJfM/BJkUFrQtrJVaht/w2X0V/D91oc9HXplW4w4l4OqNykin0bhZKl5SQToGP1v9vEXjTt1yCFpISnAW+AgZLL6Lp4AadCjiYWDthL9NnxV52DwIF3sQQ3h9/9GAUB46MqTX9vNc1y1mwzT6EuMvwpUc2v5cx/vpoXVu27S/GfydRYbZtrrf+7qmImspucjQLpWvFJ5d0i3us20+EEig/eYSeRTMDi1qDr7aqLxtkGRT1/UGvq8M5kZiVgJJ9+ApyB6yzW8tO4m67MKzpehS15bGEuWzuBC7cPchoR6FzgXCnZVar3hT/YvC8coL+tVPhadv2Pss+Tl99L7QeXEpz5UY9WWu9GbZpdcWEc8uMb7fNOLbkXYGPjXQJfIJC7gagp1ILfOvKpYFWaRmseuUh/8zPYsgrPkt56VHt0oAAgXMsrG1uUww71t0KPwLqIO+nQ/RtmRwo6mUE5KkJaMfW5oXzB3lL7Yjy8ztTqw7rwt7mcezHM/qmFoq/bx4C70CMbU73lvq/P6vlHzQSJwJs+zWv2Ki/xzGhpNlgpadfZ3JQ5LPhh89WUv3dxpM7xil6xsBwAxznClSjwGK0pV4MK/IegzI981SVC5/9bRE97TP1fpG4a0yhG4CFXXtoqRZaFgsv5N/F1SPvBlxAKIb2dXcwd91OWtaLX/CNYh6+7Tx63OwUJZxRrWMOGSnXqrm8pXZwlgL/57H5/62Pq+45rL+b6rHb7n/lBn63Xriq7DCexhNQB+UHj2ixtxKt0Fu3Ny6WTes2QC/MPbjTWBFLkrTxqws5KPKRkP6ra/aRyj9JvPH2YfYdADZB27eWIV84z47aW2lo3Ax1cGi0krz6IQCWzmtF/k4FumasVq0V6zJDqD1VJ2gZ1IsWXLOXlQVFUKP8QloHi4a2cr0s1NvVKPLqh2ipE0b+T52grKVaqCx9jeX565mODmK7XDXoSVIRZqb07oZ5qpxTlFDAMDM4hlo3gfKqI7TUCXn1Q7TW6qRo1Ov+eRpP8N6zs2ipFspXHgm86JTB34z8in3A7TKL062ltCwWfTF0Goe4mPCWfbB5BIuhrX0ZdMLeKQscdozGP58u0qs3OeqTD4Ur8NGTqj9PIo7j1IaD5Wf6mNcIC6v34Gk8wWDVhexiPl351axiDXv75o/1ncNYX76VYti/5QZufvYgXoHXVCVwEO6Bt5p3kDdyltGyQgDUEgnILllZ+hq3yGzd4yL4KP8yfga80TsbbzlMM7b7ABwLdwfDWwvQA/T42vAC7/1gFl70cXYxn3OA6p/A5No+ZnAM7yLwrgdkFquPn9c1YI3PODowiW3qMMtZj1e2MlE16Vkz9tKB9rGLcJa9ddB3MXhqTzCDY+xlgY6y8aVXiCSlQiaRPv98joVQRiISrshHTirEPRXpaW1RG+D3I5uuimpoqNrMC0ONyBm4oWw/R0emM9pd6Ct6nbdkiNHuQt6vFqYtV4Fhh1jaLYa8VUMU5A+zgvWck7aATbapw/T0zaC89Ci3yyzf8nmqnJeTlIwsUr6v8niWRQF9vhOYdvw8dAsUQ0t1YOTePFXOepZzHYcA9CCpU/hlpJOtzAHwMvCsO8FNdLB10b3QYWnjU3AOqXR6H+m6ZJNIkXdDKIPgCnzkJFvg05R//FP81uZioAze/5GgioRp0khV4X6GyvJoltnclN+BKhLtc66Gz14qYkfVrbwAsESR99Mh58HXYhjdXsh9UsqyZ9vGdKGEU/SVfpH3ambxfZXnW55ugQf4mYyOuSg9px6k5YoJUKHwVJ0Ys8/L0sNLI3U0795I89qNwQuB20Mv7YO5djfYAPSvncoxpusLsSn+ECKk0ul9ppAe/RlnIu8SGcn6k8QzkBqu3QixWPLltUegXvECcOHkQVYfP8/RkekMyijvAHsuW8iOcljMJsqrjnDVPYc5RQne26Cp9AkW5T/r91UbbVpfT1RNjmGPa1jF1Gf78f5Wi2qmc4E8BkB76Z3cRMeY9cv+Aj3eYL+z8Tg8KmDVwYfY/qYeaN5x8Fb9HVrHF6wWfr3SA8VmWKcp9BXAPRB9iGamXgCSRw65a8L9eK4VH55k/AFScUcQCpsIXAwUw9yTO9nTuhCpO4+n9CT97VOhGNRbwo8fedAnbADeThiqymOYAp4T7Yd4S+1gb9cCnysHoHLlAY6OTGdR/rO09f1wjDsmF/DeB95nnJfLXyn/9xHMlQVQB6pM8FbD+6qdl0bqdMz+LgJj9IuBJYrB0osoWvuZXrdEwdPabUQn8CvQbhsnN0ww10y6c9Mnwm0TubtmnIi8K/DhSaN1ndRjOIs8HrQFCQEWuGflCe6T0rCtXq4a+EC2srpT+QZhyxuP+ET9fdXOizWN7OyYy4LWvXiXR9DVLGbtsGVylYmZLsGKNV2DCJvnNVDHSxS1f+Y8wawM1FJBtimaqjZwjOmcpIT+RVO1j/4URC/y4dalgniFPnKRH4fRNS5jSZQgpzrMMg7MgUHbTNP+rqmcUa1sXNLsaLGafCBbAWiq2kAbywAoYBjvevAuh2nSaFR12svb8fU0o/FuAR6GifmreLhmDb8pKOIiYwB59eNqbBSSIfDltUfwCkxUBVzNu+TV60HthqrNvPhsIxfOH2R0YBJ5xWe59aMdVHKAtt3L/NZ+NxHkEnIrSkHO+ORdKz42EuUfT3Ue+UiP5WDFw9j0BJY0BniUHuj7TvjWvevhGNPJqxiitWopb1w2O+ctdjveReD9GM5JG4vyn2Uf/gHk7T+SgEHp/VtuQP0XoaVOqDF8++ekjRWs5+2CIsqrjlDPdryL4LNNRTSUbmFlQRGnKOGNrtl6DMVMOwHRZQQdQ7p986nTpRxx17giHz3JiklPNtEcM4jIQ2A8djFQBy2LhfdVO6UcD/DJh+J91c4pSnzx7eOZOcA+4/Xn6kHWdD3qT0VgXER/Vy1UG3c7drw94LUUSPHeB/wA5N+0RnlqTzA8UsDoXYWWzJQQ3F1DiOXh1qWCeFw2bgilgSvwY0nEbNJ0VYCK45hOAm97f7fysIaH+cmzkQk8wBz2uQJvYAr8ncAgxbRUC6tWPuSLQGqvuoOLVHnQux2vrQLWhqebuHDyoLbcO3U45SP5q9j/yg2WaBwzVj7YuZGIKlPJIjX65PrkxxVJTBWQdKI9fhShdcXQ1LiBo9LPO1EexfTNu/h5AbhEmgEj/PL4IwAc4rqovq/FeW1sH63n4MDNvtq3zZ0b9UWjI+HdzllywJIP9ud3rXg/8ST5SpfVbu9HHISbSj8AbSuWcS3wjOpLWLZHF416dwLlpUe5xhD+SDijWsl/9zwH228ODMvsZmxa46wm+ToVt8iLyCkReUdEjonIIWNZoYj8RkR+bzxPMpaLiPxMRI6LyNsiMjPe47uEIx5xzwRi6YdDGgMTe0pg8AnItE2K/t1TmcM+7Q92SQjeWqihIyoPeD3bod9WltCaKiEgrUE4Mtllk3wSZcnfpJSarpS6znj/I2C/UupKYL/xHmAuuoD3lejR1LFzvhOCa8XHnn89k076BAu8FWtedJNe/aihA26N4dAuQbkkCiseYDv1OsWyNd8+xF6CMaNJrl4ly11TC/yT8fqf0Nm6zeXPKc2bQIGITE5SH8YpsZTFyzRxh6T0xxpRE4JZu99Drj7PNnWY91U7N6pKHQ/ukjIukWbmlr5Ea+1S5q7cqfMMmcQVOulEpp37iSURA68KeFVEFPCMUurnwKVKqdMASqnTImJeqi4D/sOy74fGstPWBkXke/jiJvNDHNrpxxnPVnwsNU8zkVj7FsSKDybu9pwzlpmvecVnAT2p6XXg9Rh75BI718tCUE3sXbvAPwkqJNk8+Sl5qYgTIfJVSqmPDSH/jYgEy7QN4BTXOSZQ37hQ/BzMOHmX0Ix3cYeg6YQBPDByVMivV7SuW0rzoo2BeeLNGO7FwteOnyev+CwrC4p06t84euQSPd4KuOOddrb2LdI++d3oWHvTHx+zFZ/NF4D4iFvklVIfG89nROQl4HrgExGZbFjxk/Ffoj4EvmzZ/UvAx/H2wc94s+JzRdwhoQLvUG/126M7aGUpzX1PjS2aXQcbq4XqCmi5YoIvuiYTUv+ON7zd+u5J7W5EXgqSsz8pZMJFIDnWfFw+eRH530XkL83XwC3oIKeXge8am30XfT3GWH63EWXzVWDEdOtET6aLVjKJxoeeif52OwkWeCOlLRXo0aA62Nu1gDpe8hW+sD5aqoWm27TAXIPhJnBJOt6v6wlooNMVL/sLWN2pWL1LIb+zCLxTARIg+jTD45N4LflLgZdExGzrRaXUP4vIvwLbRKQRXa3sNmP7Pei4hePAHwCHbNsuzsQSKZPpJEjcwe+iWQLqnCDXa5HIqx/i1/nf5HU5yBb1oM81k1czxOh2XYZv9fHzzCu9mmukJ+rJUC6x4/0tIP28r9q5dKROV+EyM1fGbL1ngkUeD4m35rM4d41dIHLVVZMIcQ/XRqr/FPFegBwsOIsVn/fPQyzKf5YiBvjJZY8x9FEehZeNcsNH+zlJSUAq4dWGD35+/i6mSWOc/XKJB1/aZntOetOSD5qYzB4vH08e+Uy4QEQi8m6q4RwgXnGPx1+frBM9CeIOY+LhR39QSFvdMhpqN/P7j+EFo/qSmWPGrKU6UTVRTu4V9shWPFUnuKmqg61r7w0cGA/qrglGtlvziSUH0hpA7ljxscasX2p7fSVaEGP1WV5K7H0J1VashPgs9glP/egKT18RjjGdK7fAtWouXkt5OXNA9Zy08Tx3cblqyArnVq5zn5TquylzAlQZ8FM1NvR1zCS3SM/zbPmVE6tnWWrJZ8uPFQmJTBp2KVw8EWqwpGI1/wCRTgGP5Dgmdmspkb9LBH/cYDNaB0B2K/ImD+FdBG/ds5i3u/c6bqoF342iyRRuVJXQp6BYKK86wnu3z0KKle/i7bPwL8bmtplIfOe4Se7dBWSpTz7b/fGJsI6dlhnCWIK2fvqx+TET8SdIJlHceTgJvBkaaVjt5a8c4SwFDI8UsCj/2ain1rukl5ZB/Xy2MI+iys8Cz2crAWJvPcejLQkYzTapIJRvflzlk88WgU+k+yPMsnp0tqBVaKu+GPgq2srPmLCziQ6POLDOajWEoGfFTPrXTmV0YJIr8FnI6iKQVviZMabiK/Bi52IsF/1MOb8zhyx112QLiXRfRFEU4Wl0KFqxtmZ7Fs30l7gD+NT+R0iEhZ/CP1e41MEmptXXH5HB45JhzFPleKWH1cuVP+IGnIW+xljfQQJy2+SWyyYLLXmrqGWiFZ+MhF8xtGXc2vYsmqkHsKy3uY4DV3E8Lp4YufDGS6SZJW3ZJVcfP88zqg/QZeZcMp+/4Ves3mW4k83f1MPYgVjz7q3O2CZnrPnE6FsWinwmkqxMjuHatK+zWOQWq8ez8sRY6ydeUb7Y8qjXxwlYlgyCtetk2UFgitp+YRLDOtKmPMj2LhnFfVJKS51xF2YWWjd/U4/lYVwA8uqHyDs2ZGkhlwI0YscV+ZhJdorecO1GeNxqeIoHoNphXSxibBfxYmjaskELfUWI7eIhkrYsVnz5K0do2rKBlh+JTxhaqoXbZRZvi3OUjUtmcrlq8At7GbQ8K6i/lYBlVMPvnhVGOwp1kW8gfms+dy4QWeyTT4erJhU/fIKOYbFuF67do3301kpIJqZ4RuLHdKqy5IG2Rcto2LKZ6zhE85SNsbcfyTHtFI997umbwXubZ3Hh8CAMKF/aYJfs4xDXQY2ioXQLc9jHcGMTXmnj/KAw4THDlVNtFBHfhA4dHhNemc3En+bAteQjIlVJvhIo8B60ldPLWHeG3WcNoa1lp3XFaMt9MVAHpRzXf8iIIiAiIJLtrRE1ZaD+l6C+KLSW3s+BRyqZn7+LlismsKGgiM/Vg3hvC9WYS6bScsUEpkkjX5OtnJM2zqhWJpw973ffeJRb1CUEWRgnbwphsi35VN6uJTL52EQ86gT9K6ZqF02Fgu3izwkCoaeJh0sMZRXWamCJ0pkdzcRSTscI1qbd2ormImDtR7HuS8PKzUyTRu4EXgC8D4H3Ub1Zy6AOyXPJDc6oVjZe04zsOk9D6Ra2dt2rz71O9POboMeo7FEy0UTNZEqEjZMlH3mcfJaJfCoia1Lti4u10HYwJurJUKZ/vFpnZbzw7we1vzJYYWTwC2bI9K743T7VUL7uCD3tM4MnlbITb25w+12C2ecyUFcL3kXg3a2LR7uMD+apcmZe1sPkj/roXzsV1mCb/GcV62iFO1OFPucnQyVD4NORdz3RxzNCGQfQvknDspbrFaNPF/oHqkx3jZlz3cy/XgYNr2z2u3vCUQwlnAps11gedH+HUnuRHMdxe+sxBkA+UawdHuTH8x705Sl3yV28PfCq2s9L1GmBXzFVlwkEMn92d+rIUks+kSKfrlH0ROasMTEiCqzl72qgfcsd3D/ypM6fbvroB9CulqfFv8yoksQmglvk9lj0xdBQtZknuZ9v8msOtt+s26sDHsfZcjfj9sPdMYTCquHWi0AZUKNouSJL7ReXiLhbeXhO+lm9S6GOC9Kv9Dn3DRxSeLiW/DglnRWTkiHwDhgC27joRUa3F1LZeACWKJpWbmDHultpKn0CqmHuKzv9Lo/bBVZZJqCYlr4tJtlHJ2zdfS9FXZ9RwDBqWKAO8iqGxlrtRrgbdfhDOmMxuMPt0y88o/qYqJrcwdYc5QGe0vnnO2FDcxOV6w7AXeRQVE3iyEJLPl4rPt3xr8nIXQOOhazB75u3uzyqobz2CGtYxZ0jzzPaXUhr1VL3ert4AAAgAElEQVTOSRtvqR3sXbHAN6Dps+ytWNsyrOem0ie4RJr5XD3IDup5b8ks5I+W86saWhYL29RhenbPDGw3UoveLvCWz9WwbjNreJgqujhdU6orD7nkBJerBj6QrVwDvAPMAb62S/nPoW5jQ5/IJ8qSj3WfZGC15nNy4DURrpp0Cnyiju3UTpBSeBDoH7db1tV6ktDlqoFDXMfGa5qhGeRKnSukqXEDbbuX+SNnwJ8Dp9jWZhmUVx3xFeDwboEL5w/qsQBj3/J1Oitkf5fhO7UO1EJ4oXey4C3jAXNX7vTVZ52omjgnbWEadMkm1g4PMtpR6B/k78Uv7gMEEXgY7yIf82QoEfkK8P9YFk0F/i+gAPhb4H8ayx9SSu0x9nkQaAQ+B76vlPqXWI8fHdluvcfZTj8B2RkZAKphVdVDrB0epIBh5rMLbzecuaeVuezktYoaOqjRtVAHCv2hkWW2tqsBj6K99E5AF/QF2HxPA7+RIr5mlnQDerpm0l51B8NVBTSz0S/0wQZgzX4Hw7jAtKwXvq/y/NkKwRX4HOSz2iLkO8ov8NbzOSiZItDpI2afvFLq35RS05VS04FZ6MLcLxmrnzDXWQT+KuDbwNXo4ZGNInJBfN2PhFwR+GBEOH3bbiUPwJq1jzLaUUh/3xSOMZ2WQbhEmtnz8ELm5+/ivZpZrCwoghrlm3hSufIA1Cu/Be1RDJZexAeylQ9kq6/5e5dspfoh443F8r9/5En2MYfDVVfRum5pYLSPNUIHwkfoGKzepAIE3iU3uarjsH8ClEvEJGrgdTbQp5T69xDb1AK/UEr9USl1EjgOXB/dYaJ11eS6wMeBxQoaLL2IW2S2b7LQjkfRZdi+Bd5O8JSe9AnrSUpouWIC5Y1HyKsZIq/4LN/k18xTgVm/vM/AkUfKKa86Ql/tZKhQ5FUMMSX/FL8eWsjL0sMPh9r8f9pq9OzZasa6lYKFXZqvB3QR6G3qcBK+KJdM4XaZRUv1eE4bHZurOlEi/21gq+X9AyLytohsFpFJxrLLgP+wbPOhsWwMIvI9ETkkIof0DUIspFtgU3H8IFZ8uAgD26Dp1bzLGdWK9z696B1jlXc58Cb8mm+SVzOkZ88C3q/rP9xntUU8X1DEdI5RwNj8MMMUsJDtTO3tp+WKCXTlV3O7zPJdTM4W5vlEvq9xMp6qE5HHz9tz1qBj9t9X7b7P4ZJ7TFRNftchBE+jkVDSrSXxEbfIi8j/BswDfmksagNKgenAaaDV3NRhd8dRX6XUz5VS1ymlroOLYuhVun+UZBzf3mYCKikV61DH+6SUNTyM95mxm3mX6zqoM/KPsb+0ivns4kiHttq9v4WFX9cuno9l7Kjp63KQC+QxX2rfYQoC1v9MRvFUnSCvZohhJnF6SWlA34L+eR1y8bRUC/Vsp57tjp/DJTdo3r1x7PlhTupzcSQRlvxc4IhS6hMApdQnSqnPlVLngX/E75L5EPiyZb8vAR8n4Pg2clHgo8Q6GcpOGezfcoMOoWw8wme1RXg7CevTvkVmU8JJLpFmo/i1xgxT3BdBt16XgwHv71YeXuAuZuQfYxVr2PEMtDYuDcwbHs5dUwz7G28A4APZ6qYSzmEuVw36brJeBaYaLoOGg5tTV7gmy0iEyDdgcdWIyGTLuvn4g5xeBr4tIn8hIlOAK4G3EnB8C+kW2FTllo/BirekGZ7d9QZzq3bS0zeDWzt2cEdVaBeHd71+fs7BWo+H56Sf1+Uga1jF9bKQSzGiYsp0oZP310twi97irrmT590shOOAAoZpuWICfaVfDKgVsGPdrbw0Upfu7qWI6P3yccXJi8hFaD/7VKXUiLHs/0a7ahRwCrhPKXXaWPcwcC/wZ+AHSqmwZpeOk/8x4T9crgq8ve0IBP5inKNUnKziGkVl6WvcIrMT0tN48T4ENzyyn+/IbJYeP68zaAYLkbNE5ayqeogZHHMt+XHC+6qdrV33klcxxK/zv8nsb71hqe/qlJiMEMsiIZNCMc+QsrQGSqk/KKWKTIE3ln1HKXWNUupapdQ8U+CNdY8opUqVUl+JROAjxxV4H9ZbVms9zDCDU2dUa2ZYw7fCbPZxqZrLqtKHI7LkPVUn+MmSx5iT5wr8eGGaNNJQtZnPXipidvsbblhlCHIgd40r8GOwZ4EMNYDZLxwdmc4pSth8TwPe3VF3MqF4q+EnDz/G27KXC+QxXbdzydBYHz3+1/dJKd5nYMMf09ZtlzTw4rONeBdZFiQ1b026dSZ2srj8H6T/i88ggbcOttZblltdHWWWbYohr2aI+fm7GKaA62UhHwDemPubOMxCHwAf5V+ms1sW3zx2Q0Pst6nDPM9dAQPCLrmL9zaQx85zY2kVLDqoQyqfNte6KYbtZEnummA++VwV+SgE3p6nBnQ42Y8Ajwr0aZuVovq1K29ulT/XSybj/TpI+3ldgcr8LL7PqlB1E/B2B9vbJZcwM0/60hp0EyRvTTAfejy+9Uzxy6fQJ586XIH31Ty1P0xM0TNy1Myt2kl56VEt7GXo9L81Q5yfNIHyqiOUVx3RBT+ygLbfglo3QU/IshUnySs+6wr8OKKlWgKrkI1LoouwyRKRt5OLAm/Pbz/RWcydcPC57120gJ61M2EA8uqHUAif/UMRsgXe65rF7TKLerYnrPfJ5BN0moQp+af03Ynpl/coCvKH09s5l5TxltrB6k0Wz0M/YbJPukDWinw6SbTAOxUvmairKoWb4h8q8sTM1NcLo9sLWVrVCoN6BqvXKNhx8zUHHXbOXG6XWZSXHtUFSTyKvOKzTMmSuxGX+BmmAHVC/JOg3FmuEZGFIp8rOeGDiLtpwe9CD6Ca9VdDzfw0ccraOACUQQc13PF0O96v+1dlo5vDdDHlFZ91rfhxxi0yWw/Km9XFgoZNZorvPDPIQpFPF7EK/KUODyds9VlBVzs6uNlI6UvExbXH0KtzuU+TxqyvlvSLvIXMyD/GlPxTTGKYEk7hdS26ccWq2of0XWqndWkqXDXpdhPHRpaJfCbXZHUS80j2M6x3O/1AL5RyPNByDyb2Ttn4LPvlVQyxTR3W+T+ymA1/hHq2U8AwBQzrC1cW3pG4RMe1ai4AN6pK/loeo6Fxs/6PJDU2PjfIgjj5L6T5+MGEOt4LjoOwOwywrul6lPZ1d9C44kV/itUBxk52Mv3w1vfVGJWdJrGyoIh5qpyZrT0ZEQsfD+ekjenqijFZLV1yl7dlL6sfV7ACuAeYgiW6xh1wDUUWWfLpsOKdjhmphR6KCGev9gK74BDXwRI1tq6qOQD1U+Xsrx+A0YFJtJbeD+iUwd7lcXY9Q7iOQ/oux2VcsLrTUvavA1tUjUsoskjkU41dyBMl7lFmkOyFtrXLaLliQmCJPMtjbulLgcuxPPcLm1g8pnJTtrNoaKsbWTOOOF8u/qphIRkvg66RO2GyQORT7VGyi3kixB1imrlq0gurH1e6Jmod+mER+b198wNzsFsnDHl0XHGuTflfXQTTOZbubrgkGTMa7KXCuXhqT/gnQrmx8RGTBSIPqXPVJEvco0wuZseY3dfc9xSqSPTMz2p8lk1e8Vk9E9CslWopvO0pPUknVfF/jAxkZm9uXbhcxuL9rXbVlHCK/hVTxxakdwlLFgy8hiJaEXa6lbMLeyKJUNxDVXIyqYP20js5QjlTOMXZWh0jPjxSwMqCIq5Vc5nLToYp4CQlDBf7ByUf4ClevK0R7y+DNZ6l/DTdHXBJNtvUYdgNsyrfc2e4xkgWJCgrVfBPtqWJFGOzLasgx3vyROl3txf5MDHjvy1lznbU3grAgof3cuCRSrZTzxUcZ9nDbTAI9MJQRx5P8EN2UE8Bw6xh1ZjSey4u2YAZOrlwyh5/NE1IkQ/nk4/XZ58pPv+/R6m+iBKUZZnIRyvu4baf6BfYsKP1kQp/FAIfyoL3EJgaGHwhkTfld/iyR3rXEzRi5nLVwCGu4xJpjrxPLi4ZwLVqLgt372Fu7U72Vi5wsOLBFfnIRD4in7yIbBaRMyLSbVlWKCK/EZHfG8+TjOUiIj8TkeMi8raIzLTs811j+9+LyHej+1CRCnwkE5EsfvJi/GkDQjKR0P51y7pgGSPtD7PKvMfhUQ15Px3yC72RJrggf5hZHPIdNVRI5AeylTnso2Uw3Gdzccks3pa9YwXeJSYiHXh9FviGbdmPgP1KqSuB/cZ7gLnoIt1XAt8D2kBfFIAW4L8B1wMt5oUhNF8gOoEPhbNIz31lp34RcbX3iYGPi6PMGGleWMyBUvs6485idGBSQNSMp/QkHw+V8pPbH4u0oyy4fS+riyLe3MUl7byq9rN6uRor8GGteBcnIhJ5pdTrwJBtcS1+P8o/oQP7zOXPKc2bQIGITAb+GviNUmpIKXUW+A1jLxwxEkkkTJAZph7Yu2KBPxGYXaRDWeIlwCYizxbplHbAzPde7LB9h+CpPUF54xE8VSeYxDBPFDZFNYDq/SXcGfnmLi5p5S21g4MrbtZ5adxImoQQTwjlpWaRbuPZzGR/GfAflu0+NJYFWx6GSNMahPKFB1lnTWxlim0NWrzNhxP2SUc1Dsud3puYeWYGoLL2QGBsu03wh0cK2C2zmM8ulrOee4i+2vYLUe/h4pIe9i5a4E/fAa6bJgEkI4TSaTBAhVg+tgGR76FdPcAXGWulm4MflxIo4A4RMhfbBN6a6MsU1DpdcWbt8CCjdxXqdf227UGfcNYi2VYRr8B/QpqumIAseQS4YszXJynRF5heS3/M9RWKF/Lv4neqgUukmQ+A93BxyS3uVh5K20/r/4tZ8cluxUeUwiBTBkUzi3hE/hMRmayUOm24Y84Yyz8EvmzZ7kvAx8byGtvyDqeGlVI/B34OIDJDXwgunqh/6IsBJuqWzL2twugT4on6uRu/aJvP5kBrHbTUCazXzawsKGL1cuVvoxq/UBfrgdDRHxTCYrSbpkyX2dvLAp3/3dwPdK6ZAYFVCtbIWJeNMaA6n10U1Q6wpvhR8ip05Ew929lOPXtaF7KhuYlz0ub7bvY5fWEuLlmI94sg2xSr2wm03l0SSjzumpcBM0Lmu8Buy/K7jSibrwIjhjvnX4BbRGSSMeB6i7EsDBc4L7aLptXidkrFWxFinb1d+2vjeXRAjxMfrrrKt8n1snBscelidLFsa1vWAVYL13GIKZzS1Y6AAiNH+hz24V1O1tRhdXGJlhs+2q9fuC6ZpBJRnLyIbEXbzsXoe6IWtO26Dbgc+AC4TSk1JCICPIkeVP0DsEgpdcho517gIaPZR5RSYR3MItco6LItDeauwT9w+uk5fHHwVhzcNXmrhlhZUMRbagd7v7XA+XYRy36WtvKeN6x7a2Fh07cegbuGJQq6jeLE1vVlOgf8I/mrKGCYD2RrkA65uGQ381Q5s9a+F1ig2/z/OUbWQGwx8pFuk8z9E0VOTYa6RsHOEFvYhd7pxw8y8PpV49nMbmemMrUWoXCyMiwXirx/NkS+w2GfYBE35sBrMVRuOaCjCZwo00W4VxYUcUa1Mod9zB9yQyJdco9rgHeA1fcov+vGHh8f90SoSLdJ5v6JInKRz4LcNX8Ksz6SL92w6u1043fjmIM+3fhPpmAx76YlblobHbZ19tfBko4Vw8G+mwLvAsztLftsU4c5SwEd1HCqsARj6kHEmH8gF5dMxTw/G7ZsZuuie/1CbxpfEXEpmSPCmUOWZKEMxyeE/3EdrvyfooV6idLibhV4c32wxyn9GP2SxVUT7GS0r7e6gjrEf5tq375GMdpRSE/7TPq7pnKWgqhDKOcAC++LahcXl7QxTRqZu2WnvruOpKaxS1iyQOT/RORX50iE3kHs1xh3PRGFaVnbOad9/5+eC7wAhMIU8G70ybzJYZ1h5as/TQjwUw6PFHA173JGtUbaUf5TVTL0dF7E27u4pJs9vQtpWS+UHzwSWLs44M46yiSA45gsEHmTaIQ+Cqt+AH85sbD7BLlIBKwn9B2A5bH3Lxfou4d+h0cnyFrlF/lOGO0opL9vCqcowXubPpQ3hJV+o9JZKl1csglvuU6u17N7pp5H71Sk3iVismDg1Z5qONE5351SDUN8uTESlInSIdVwZe0B6tnO/yFtLHwIlj7SynUc4muylRcAbyd4q2GiamITiylgmFtkdhyfxcUlvXxf5VE05TM3C2UAOTXwascaPhnP/mYbn1iWJ+oCYp58EYi9OcHLOpHKxDLBq33lHdzbtRWWwFVPHwa1mB8DZyngOg5x5W54a94O7mCYOWof94+sAaAgf5j3VTsvXtOItxsXl6zjAZ4K9M9H7FZ1gay05JNJMqpExVEdynqbWgYsUajfTUC+dl7H1pub1Z7gPinVFe2Nmq706/WeqhM8wqqcjLP39uhbe5fcxXsbyJ2KptoNtC1a5net+oTebs27lrydLPHJp+qL/STI63iI0u0TIi6/tfR+v8B34gv77O+bogW+Fx2tY0bs9OrB2vUsD+m7z1aOlJXjfSj8di5ZTKFOPbKYTTpFiBtxEzVZIPJ/TvHxrAO3nxDZQG44Qg3YGlhvQe1CXwz7191A89qN8LT48+QYk7fKS4/6RN33MNoY7S7kLAVsfrohzs+QWbQMwilK4Dvp7olLMvE+o59flh5t3JhJ/HyRNm6UTTiyQOTThV3YUyT2dsqgad0G1rM8UMAtjxo6xsbim88exQyO5Zy7ZkthA0eZ7rprxgm+O9WwUXCJDszIVCI3frNI5NPhC3M6ZqLEPgLKYO66nXRQowubOE2YGkD7Kp1ycBfralKnKOFaNZe7lQevPZ9OlnKI6+jjCl8oqUtuo9403M/F+LPIRlzJbXyTBSIfLq1Bsgkm6J8QnzvHwap3iBoo4RQ9K2aOteDNePpu9GCUfX0v0An9a6fS0z6TO0ee55v8ms1V2e+2+Vw9yClKGKaADdua0t0dlxSwtLkVdVLYseVW1BGh/OQRS5CC67IJRRaIvJV0jWxHmvgoFuEPYtUbkTVbRu4ZmxLBKUOmU7Fjy36j3YW8OzSLe5/NbrfNpcB+5nCKEk5RwiGuY9lfpLtXLsnmEmnG+4wu8E0h9LTP1P8R15oPS5aJfDqJ5QLjJPxO7dhmy5pUw+hdhTRs2Rxc3O04+CwrGw/gqTrBnYXt8HA0/c88fqfaOUkJJ0dKOEuBtub/mO5euaQSeVqRVz/kryoNpMaaz5TwyejIQpFP5xedqGMHE3yL0D+v4AdAN2z9y3vHDLY6DkAFuQgcbL+Z+6SUFx9uxPtxIvqfPo4xneGRAkYHJjE8okU+V8YZXCJkF4yuKQxRTWq8DL5GRhbOeE03iZwZa7aHpU1D6K9wKHhix2mWrLncDDWrBir0BCnvo+i48ivh94vgAuXhOYnk9iD9XAP8WB2mp2+Gb6LXKJM4mV+CN0jVLZfc4lW1n4PtNwfWgnUJSxZa8pD+26ZkHN9u2UeY2TLYyb5YV7yiQleeWjs8yDZ1GL4DN9yzn1p1mPWswFvhsG8G8g5wcqREC7xv8FkYHilIb8dcUsYtMhtP44nAhW7MfFiyxJI/A1yS7k6kCOudgqXYSTChN09wq1VfDPTCqGcSbNeiONpZSE91IVfVHqanayZ4FAWlw1mRz+ZSYNnwIKMdhYGFWAb8dXddcp9rgP6uqfouNaKY+VzlTFRbh7XkRWSziJwRkW7LsnUi0isib4vISyJSYCwvEZHPROSY8Xjass8sEXlHRI6LyM+MWrBxkIvWvFPbEcyUNS8AZmhlGTQ0btYCbwut7FlrhGN2Cycp4S21g7fUjoR/gkTwfZXHjaqSV9QORrsLA//Uvmgj4VW1n3nKnRWV64yoBlqqhe0/EvJ+OoT6QKg8eUBXnx7j2nT98iZhE5SJyI1oGXlOKVVhLLsFOKCU+rOIrAVQSq0UkRLgV+Z2tnbeAv4OeBPYA/xMKbU3bAfliwp+THBLPt0/ZjKPb207gltRa5IzW8HxgNfmwyxkXjHETfkdLGYTC57di3dRXJ1OKM+oPqZwSvtiHdI9UAYt1XHaCy5Zx53A71QDH8hWVm9SuvjOmxBoFAWbzBgr6TYsTc4Aj6PUvycmQZlS6nVgyLbsVaWUOa/2TeBLodoQkcnARKXUQaWvKs9hC4CKnXR/8Rli0cNYix7LeycGAI9iSr6OOq/htbQLvHe3zoU/T5UzUTXRv3uqX+Dt4w/G+1fV/vR01iVtvGB9U4ZWk4sheX75dOtM7CRi4PVewGqRTxGRoyLyWxH5mrHsMuBDyzYfGsscEZHvicghETkEf4igC+n+ATJQ6CEwtj6E/7KAYTbe3szPZDT67iUYby1sp56XpYfmvqfGJFwDxuToOdh1MwDXqrmp7axL2jijWmnse4G1w4PkVQzpiBsXR+ISeRF5GJ0px7ywngYuV0rNAJYBL4rIRMDptiKon0gp9XOl1HVKqevgImNpuMGGXBZ6KxHmvbGKoj1KskwXIaFG4Sk9SQHD7Phl8KaSnabY7k83Rbu99E7/wmCWPNrd5O0xZkO65Cw3qkrf60ukGTqE0e2FfFZbROUrBxz2SLcrNzOIObpGRL4LfBOYbbhgUEr9Efij8fqwiPQB09CWu9Wl8yUgimk5iY5NTxbJ6qe9XUvUTaSYQl8GTY0beJg19JV+keekn3mqnJdD7Op9Bu5WHqZ29Sc0Jv1u5WGYSTzAk5SoU0yTRi5XDdAOqx9XsALnOxBrhA2wsqAIb+K65ZKhDFPA2uFBAEa3F/qsd/krhYcTIfbMJaKLrIEYLXkR+QawEpinlPqDZfl/FZELjNdTgSuBE0qp08D/EpGvGlE1dwO7Yzl2aBKRITIRfUgzVt+8nV6dtbJ/7VRK20/zjOrjZenBG+LXmIMuwXaiysNE1YS3x78umiyQdov9Oennb/gVR0emU8Aw3i9CY/uLQVMqO1ryvbB6k+Jy1cC1ai4tg5H3xyW7eFv2MtpRyOjThf4JUca50l851S0LGIRIQii3AgeBr4jIhyLSCDwJ/CXwG1uo5I3A2yLy/wHbgSVKKXPQtgk9Bn4c6CPQj59g0i20qTh+PIXG8Qlmf98UtqnDbJgXPJvjPuC1kRqq6GIdy3053E1B/Vw9yPdV3pj9zMFT7259MeigJmD991Ue/V1TGe0u5DoOMfmjPuec+E59t71v7HqRt2Uvdxa2c6fjTi65QEudjL3gdxsPF0eyoMbrFxV8D+2uiHZCVLpdPIk+vlN7Dm4ba8xwsJqxljBKdYHAHvAG8cu/qvb7/OR5FUN8lH8Zd/ECp4xEYTPyj3GLzB6z3zxVzl08z2I28fDIGqbknwJgMZs4J214O0F6lT8NQ4UKjO0Ph7X+bZm/1q1L7rP6m8ofRWaeK451X52K/0RLuo1GK6a7JvIQyiyZ8WoS7czXdPvy0338MBhCLxXnmXvPS+zpXYi3XFvoTxQ2seyyNqiC1X03+ZJBzag6RlHfH/yFxCsUv8r/Gwp368gYKy9LDz3HZ9DcvRGAnuJC8iqG2Jc/h3o1zAYK/KUMe4FdMtYlE6zf4J/lWwwb6ySj/oouiedVtZ+DfTfpGsa70t2bdBC9Px6yNndNNKT7r5/s40fotrEXQC6DvpWTocIfYcMSHZr2RGETD4+s4YaP9jN5W19AYfCD7Tf7re1eoF+4bOQjds4bG744UTUF5poBPvuHIko4xf0jT+qatVbfe6QWvO1C0Nq4lKaeoFu75Ai3yGz/uegSMVlmyceKPdNjOo6fiGPH2I4p8Fb3BlDadZr9VTfwGjXM4BhDHXmcooS2LqOcYCP0754aKL6dtrY6YXSgkIXFeyhXR3iSB7j59oMMbcujqO8p/wBZMfyuWrhKGblzduHsew+VFNN+oTL2a16xkeayjTSpDTq0Dh1ud1YO8k5EX5BLNrB2eFBXQTNdjRBBjYVLSb+hl16yyJJPxA+VC7nonYjAmremMkA/l1cd4XU5yCYWs7BrD3fxAtfLQvDooskH195MXs1Q6CgX87VH8d7ts5jOUTZva6CaLgZLLwqw0r+2S/Hu0Cw9eaXM1k4kRVGCrTfaf2qomYmqiWdUHzf3ugKfS0xUTawsKKKlTihfeQRVITqNtnWcyc1G6UgWWvLxZqRMp1WfhmObRY/LYPuPhLuGB1mU/6wup9YD0qmgC9gFe3sXUKJaoUt8wjnaaUsMZvWHgz9vfb9w67Yd1LOdxq4X8VSdoGjRZ4H77oIJvcp/obEKfKT0E2jRW9qf8I/KN4A7uayPFWo9yy5ry/pCKS5wTtp8r2+XWSxVrfq8HQDlEaRbaSs/4WGUmXIXEJs/HrLKkk806YypT8ZxHax5w3r3bDmBOinUb1KMrimkbe0yVi9XyKDSbpPH8Yn6S9TpQFfTyu5mbHoEq3CXQV/tZOZW7QSgcfeLsAud591u+feij2c+Q3QCbxLKojfyzN8npSzOcwU+V7lGmimvOgJl0Lkcfa7X49Z8dSALLflEky7LPlY/fZj9HDJR9rdPRf5K+f3p5sCVKeb4nwPE2S6mdiu6DObW7qS067Tfb288j36jMLgYP215HU2oZKi+mNvVKJpKnwBwa7/mMJ+gLfpt6jD/0vggeSNDepKUea64E6N8ZKklH/utS3DSYdkn+nhGNSlT4I3yfy2LRVfUsUawDKBvb7stj14Y/UGhs8Cb2Cz6YQr8kTbWtsNZ25GESjrt49QX9GetXHmAlismsLGrOcKGXbKd95bM4iY6mJ+/y2/NuwSQZSKfChFOtdgn4Vj1wGJ0+tUyPe2/f9HU8FEs/eh5yt2EHmy17Ht0ZHqgpR0s14yTSH9KZCUOndqyU6wvON4K+H21Tqrm/bp/tVvsO7eYqJrwbgFZcZ7XqGFr172o/2rO3QD/4Guu5I+PnSwT+VSSSrGP9lhhtt2OdsV06kdD42ZngXcScbvw2sXXaqkPGImiKhRz1+0k76dD/vYjEXY70Qi+9YJjvD5LAd5ueEfN5cDTlSztaAXAW1kbHpoAACAASURBVAE/rnowgkZdMo0zqnVMmorP1YM09z2FfK6gQ9jEYlSRIP9ouCTdFAcBuCIflk9IneAn6BimCPcCxbB17b3+dVYBthJKXIOJfQf6YrJG2Ns3n4L84cBp5pG2H+kx7ViFvhP6vzWV1csVC/t+zc1LDrJl5B5WHz/PhZ2D/JAnoji4SybgvQ+KGGDa8fO+ZTeqSi6Qx/CUnvS5B/u7prKzzJiMF8tAfo6TxSKfDL98OFIh9gkUeoBiaF25VIcWhhLgSHAS+n5YteUh6BCdCTCai0csx7Rjj9fvhfLSo3ifgZvyO6BbGO0u9BVE8W6Joy8uKcX7DPzk4cegQ1j9uGL1LsXrcpDP1YN+92MvrKp6iO3Ua/dkRbp7nWji17ksSlBmYo0siSdePpEkKzInXLtBEpaZETYVQDU0rdtA27eW+X3tJvGIrzWKp4IQyaISSLDwOHNMwIy2MWP3rcnYymBu1U492cslK/B2wo5qqF9u0yh7+gtzkt8S7b5hMfhDimNNUJbp/vgE1nh1iYRkuXSibc9hpt8AtK1d5mxhx4NpoZ/CH6Vj9ekng2Dt2j+bUy4cj+Io04OmRXbJLG5UlUyu6qN+lyHw5u9ppsnotzzMdd0Ca9LS3YwmC0XeKnzpcNmEI9GCH6qtEMcwLFn1dfH55n04iuW5CB5BiDZCJh5CHSPEhK2WKyZw+vZSLpDHMqKWrUtoXpeDvMvVqLOGsWod8HeavwGWeR/BrPhsIzH65k6GSirWkyxel06wSVAOyyuA9fqlPK60le3Bb2nHXHAkzkIlAcSRX+RTIpvZaHXZEDxfvktmYl6MPeqEHu8xcRpX6iCBRka2XxwCyUJL3k4mWvNOJMLCD7a/bVk/sBy4C33yDwBvAp+GschTSoR3CZFijbQxhL1lvUC9Iq9iiM+VG0KZLZiF47+v8vCuh9O3G4VgIorcypTzO3OIpPzfZhE5IyLdlmVeEfnIKP13TERutax7UESOi8i/ichfW5Z/w1h2XER+lPiPkk3EK/hO+34CnIOLofzkEb3oFJY/QKaf/FGKfjirrQyeUX20XDGBGfnHuEAei7+LLknnctWArDjP6k7FsyzCuxzkM+UcGjnGRRiqIlS2kTjjNWx0jYjciP4qn1NKVRjLvMCnSqn1tm2vArYC1wNfRJcHnWasfh/478CHwL8CDUqp98J2cEx0jUkmRtnESywuHfs+lzLWFZIIgY/1TxOvmyqMW8fqtjFdM/Wwfb3wgOrjPinlctVAvmx1TD08T5VTwknXT59BrN6lfIPm6p8FuViNteLHXOTt53gM41gRrU8V4UQ+gdE1SqnXgaFw2xnUAr9QSv1RKXUSXbT7euNxXCl1Qin1n8AvjG0TRLa4bMIRi4Vv3/4T4PfE7wr5hMS6mGJtI8znsP/ZjbGH+l2K+Uaqyw+CCPyNqpK7eJ5TTImxby6JZJs6rN1qllxIUuJgxYcV+GBkioCHI7F6Fo9P/gERedtw50wyll0G/Idlmw+NZcGWuwQlEWIfy/7JnPAVb9tBxN7+p6+DHbW3svHZZry7wdsDdysPr6r9bFOH8e7Wm9285CA9fTOoGunkjGp1QyvTiPch6OmayZr2RwMt9kiT2AWQLWKeGmIV+TagFJgOnAZajeVOtw8qxHJHROR7InJIRA7BHyLsUq5Y83YSJfbhHqkkEWLvwABQrQV+Ydce5HPFhV8fZGlZK89JPyWcoqdrJlKk+Fw9qNMvdwujA5O4RJpdl02aOKNaufDvB/WbcKIesxUfCbl5cYhJ5JVSnyilPldKnQf+Ee2OAW2hf9my6ZeAj0MsD9b+z5VS1ymlroOLYuliDhKv2GciCbTqzT//dlhYuUfHTO/SCdTaupax+vh5Xny5UYtIJ6xZ8ajPJZBXfBavZXTJTX2QOuapci6RZj67qoiWaqOkX1nY3UKQ6ed8OBJvrMYUJy8ik5VSp4238/HnfXsZeFFENqAHXq8E3kJb8leKyBTgI+DbwB3xdDxxxbGzjWiLnKS7iHk44u3fOXyDs1YrzywqsgkohvJXjsK7+rVvYo3xerS7EO9yvdvdysMdPMK0RY0x9sclGl6WHgC8H6PdaNX6pv9GVcnsRW/ojYImHcv0iLHMIJIQyq3AQeArIvKhiDQC/yAi74jI28BNwA8BlFLvAtuA94B/Bu43LP4/Aw8A/wL0ANuMbRNMrrpsnIjW1ZLpln2C3DefMnZ25AC8mTcL+Z2itWrp2LQHu3TO/TlAad/HvDRSB2gr0yV1eGt1Wuj3VTuz+7p0DprFpCjpWCb8N5KjX1mYoMyKk/WXK+GU0RKtJZyplj3E3jdLuKU9tNKpVKD1te2RVzPEjPxj/IPMZl+MvXGJD28nUASy26hFbPoLQk58CiXWsa5LFdGI/LhOUDaerHkrueSzT3C/BvAXJLcus6cptiwbHZjEMAVsVO3cqCpdP32KmQPcWrWDpWWt5C0Z0r56p1q/AWS6iIciebqV5blrxqtfPhS54rOP5be1+eft+W2skRt2y966qvYE90mp7/3rxsMlPry7tUsmEl5Ureztmw/94i9Ab3IxCU6Gl+kXgPjIQUsexq81byWeOPlMIZa+OETcOGHNWGli5CW/iY6A+rAu8fO5ejBigQdYzjq/wJuTo3KW5OpVjoq8i59YhDKTxD7OfjhVszIxhd5My3xYyKsZ0gXBfxvfYV38zAH2MyeqfVbxCHhs44UebC6bSDOZZrMbJ35yQOSD/UiuNe8nVtHOFLGPtg+2Ablwt/bFOmPlgW2VrCwocqtHJZC7lYevHT/P0ZHpnFGt4XcwmCaNqD9NYO7KnYGD4hVAPZGlms4Kkq9TOSDyLpETb9bLdAp+nEIfigEdQvm6HNTpbXdHvuvlqgHvF6PsWo7j/Tq+1M5TX+7Xs4o7Ctl4ezN3qxCDITY2lDVxlOn+co5lUPnKAfq2TM7BWq7JI8dF3rXmx5KsnPapII7jWq35YOUCgSf4IUvnRW5x7mMOt360I/Z+5SDe38IgxazuVMj/9GeUlL9TPCdBZzbh7Ql8f07aWMH6gBquB3ffTOm3TlsipUyXTSxZJ9N9l5oafcpxkXcJTrwneDrz3iSH1Z2KNX2PcIoSHaMdBu9tcIoSXhupSVqfsglrYZZLpFmnKTAnnPVCU9UG352S1XVzrZoLwA1l+wO+9zOqlXPShqf2BDsabyWv+CxUqBiTlo1fckTkQ/3xXWs+OIkSzFSLfaTHCuKbNwfvzIE8M9VBL9AvFDCsK2mFwSwnONpdyOpOxatqvy+efry4cLy36eeWQVg/shzvQ36LfPXjKmD+QduKZRS1f4ZcfZ6X0LOKL1cNrGINr6r9HOy6mRuq9uO9DdYOD/ISdTyj+pjPLtaznNGOQlhjmf8Tl19+fFjxkPUzXq2Eiqker7NgoyHRcfKpiLuP5Bi2CIyL8c+AtdaANZJieVae4PQ1pXi7Ccm1ai7XyF6mdSpfeN/hxqt8uVjeV+1Mk0bmqXL+Unp4IaLPk72sHR7UImzJCUQnY61u0/VSBtvrhH9XTUznGLPb39BFQqoF6VT+bYv9WUXnVu3kKNMZHilg9AeFurTlKdAXcyfRzmVXzbie8eqEa82HJ9EnfSqs+9jbHzx4IZ5XTkAdtG5Z6hOfj4dK+fE7DwYE/Hk7taVqzVQ5TIFf4A1LtWpE+xq8FfDSiLZCXx4HAg+wsqDIfze0y3g4zCQ2LwLltUe4FjhLAQ/wpF7XC7JJ+ePijW0XPLsXOmHvigWsYD2jTxfqC0XWDr6mVo9ySOTD/eFdoQ9PMoQ5FYVIQuEcZVP0rc+YwTE8tSc4J23k1Q9BMVx0wSA/WfJYQL6aH1c9yNWFh7mheT8TVROgB1zLq44EJDsbXVPI6scVcpditKOQGRxzPLa30+/myCYmqibeV+2O6wKSudmF3bocoAxKOMW05YqfXPYYPYtm6otCr23fXmio2sxV9xz2vW+u3AhPA7sg7/lQBesy1YpPvQ7lkMi7JI5MrQwVqt0IMf3yA7B39wL6107lc/UgH+VfhtojzMg/xtDTeXg74S21A+962EE9PV0zeeOa2VwvbQC8Rg1P8sBYK7XX//p6WegYjnlHlV8oWwaj/Khp4Ixq5VLg4ZE1vEaNo5Psb/jV2Nwy/Q6PbuBx2Fu5ADpBLrfcDcGYi8PWtfcynWPacjczixq5iEYLCnHTDYcnh3zyEJmP1vXPR06m+NXjbcshO6U5saYYnfyqRrGq9GGmcIoPZCuvqv0cHZnOaHehT7h3NGrfcEu1sHq5crZWTT//EoWn9CQrWM8548Jgsk0d5uRICVPyT3G7zPIt/77KS3t1qpZBOFs4th//f3vnH1xVeebxz4Orxl0VjLFNqnUhURvwxyA4rhiWIjhtwR8gWEdcqwuhKtVRF3UEiiV0rW2WSnectf5YItbdgrKIxLVktg6acROpVhQFDSpBpqsSmIhBnTVulWf/eN9z78nN/f0j95x738/MnXvy3nPued+8537Pe573eZ9n+a5DsEPMwrGJwqU6mnGPdtE01yx4uon7uZul7GGkSdqS2FMyNd58ST1ULD1A5/CJjL/jLVhP9P/9GUQFPvYmXw6j+LK1yRd7MqXUGIr/Zz5H9xl+T+/A93/gV4ygL+LG19973ADTwey5JuPU8l/E2I1jR/MzYdkpw7he6hhpZgZp+r6ZjH1Iu+lqHUd/eyVvTR4fMXM0dcDF/I6TdU6ket7CoXTcObPB+95rtDryRPF85QRO581Bq1Mrqj427e0wC8fGd7/JmL/fysk6h8ekh007ZzO+9S1m37Fp4Eli7fKpXhAZrU9Y8RwjhvexjbEDnxLyGpys9CkxkU8HZ5vPjKFyj8yX7T7e8XEe6b3R4kTQ0YJuHMaJBz/gTGmjpqGbF2+YyoK6X0X39wuRN6noN0P491kFyzcqD2k3s3a2Rb7iNGmkp7M2eoP4yPjZAzRNhC3dF/AnWRvZ/2J+B5iQu00dxg/9K13MyTrH+JsvSe8/0tRqbObH6gL26728oy1cCIxp2ApAA50sP97se9HBZ+hpreVrclvEDfQdbTGTnf4bG3CFjGfemaa+d9Uv9rmhEv8px+OzOC8PX8KXLZdMoaellsaWNdFIlEljyUN5jOIzo8TMNZD+478z22TOUIcjzuV8scdak43nQnkDUA8tM66isXWN+WwnHPqhMOwpZUHjSk5hFzN5irqWvVF3QP9oMx7eqv16YL4xbYCZtHyFc1jbOs/cJOzIdMEKc55dnMIDLQujx0LUHbFaqaj6mFHD9zCWbZwm2aUmPEunsYr5vMZYerpHmSiP/lSI9n8AwESY0PAcI+ijrXWWSaPoUQ9LVyxhFfMjRT2ttcyZ8QhrJ8yLJvfwk+7o2+/7foY514TVz7GleYqpY+SU8Uw1qUS8WCJfCIFP31xTgiIPzjZfSIoRdz7bc8YR+qMx4jETlt65hLub74mOEqugZfVVNN6xxgjfRKhu3M0o9rBl7pSoAKayN1ebY5euWMLdnfdAr8k09dvhVxuTj59EiTBiM1WdcYALhrfnJXjaOt1KV/fZxsYeL3mKPf+0FRtomztrkFkrUr962LzifOPj7n+68e+XjWnFP29i/5fMBG7HLlLzj+LTFflSG8XnUeRF5BHgYmC/qp5hy54AvmV3GQH0qepYERmJyeH6tv3sD6p6gz1mPPAocBSwCbhF07jDFE7kwQl9thQrwUg25/UfcyyMBP4dI0r1ROOVe3gLebxFOzNt+Ua7b7w49P5jLU++N53ZzZuiNxDPOySRCSM2HaH3boNzeU8E+WDhkfD1fXbxks8bKK6YxwvN7D2tVJmAYVuapxi3Rv/+udrNfYvW5mx5hLWXzDNivwjcKB7yLfKTMF32mCfyMZ/fCxxU1Z9akX8mwX4vA7dg7sWbgPtUtS12v8HHZSPy4IR+KChmNqlMzh0j9J6AgBnV72DwKBVgMlHzwEYGenekwh86IZP9qxgk8tNmbODxitms/CLN70qTh7SbnpbagRPIHqnMUhAdZQ/yeoklHTfHBCuTPSVpJ4lHTbkJPGQi8inT/6nqC1a8ByEiAlwBTEn2HSJSAxyrqlvs349hxkgpRd4RZIqZfjGTtIX+fT+Bz46NitEe326emcATrHboXl1D3YS9g80QqUhnX/8NwB8OAAYI/bkym5UZnDodLtXRrKOPnnjmonQE3rspDEqu7ZGp/7q3vy9941LMk9AOchB4R645Xv8W2Keq7/rKRonIa5geWaqq/w2cCLzv2+d9WxYXEbmOyPB9eI5VTMV+3Gg+F4qdZzdTsbdCDwwaPcYZhdYds3dwYSaTiPGeEDx6SDzSrwcmK8tOGVYQ//mnpYtWxvOpjmZ871tRs1Kim1MyT5lB5LJAyXfsIjB9lI0/fCb7FILgePHlKvJzgLW+v/cCJ6vqR9YGv1FETgfiPVYktBOp6sPAw+CZa7IhE/FxQp8bxRZ6rw6Quh7+uiYQe49c7cre8bFPCH6xTyT0vXBv3Y0sbIWmAi2Q2q7TeEPaqOg7QP/Oyvj29yET90RkE3ys2ARH4CEHP3kR+QtgFvCEV6aqX6jqR3Z7K9ANnIYZuZ/kO/wk4MNsz10YgtUx4SMoP7p0fO1j9/kkw1eGJMszCwnNImPZxl2XLmbhkZmfMh3ekDbW6VYzAQuDnzSKKvDJ1k2ke60F5ZosLrkshroQ2KmqETOMiJwgIofZ7VrgVGC3qu4FPhWR86wd/xoggyRrjnAQpB9VumKfDVmIfjyhT+FpM7W7k25O4dh12dQxPa6Q8UybsQEmwpzVj6Q+IO8Cvy/BK9n+6X5vMQjeYDGluUZE1mL8DKpE5H1gmaq2AFcy0FQDMAn4qYh8CXwF3KCqXqi4BURdKNsYkknXTM0IzmyTO5nYyIeCVNdAPuqbwuzj8RmpE13YWOtUmdAIAE051CwVk3QCZ7GKETP6WNs8z9xgEsXSz4vA55p6MsgET+ChZBdD+cnmx+uEPj8EReg90qlPrnVOIfQwWOh97pxP/ud0ANZzOadJI03XQ9NDOVYpAZN0Aku5mxH0MYI+5rOKqZe8ONilFHIQ+GLEJSrGzWCoBb7sV7zG4oS+eARN6CF1nfJR5yRiH280763urAf9htB0jwl1vOnM2ezeXp00AXa2NH0batq7TTwdiC4MayeNVaupBD6fQpvpdzmR91OGAcocQ0sQH7EznZjNhiQimMxrpxfO/9lmbtYKnj84mZrt3dRekX+BB7ir3SbettElIwHIIHG4hZTkO6qoE/hccSKfkGB3XLgIqtAXWuyzm5Dc0jyF41s+p7+90gQSK9CleJj8nDc5HSYniI0PGY7iizl6z/f50yX4OlEmIp9t5we/A8NDEIUe0l9Qk4snThwSjea9cL021MDoutdY2b4gy3On5j7pR/88jNErXk0zFEO89uQ7HHVQr5VYwqEPZSLyuRCOjgwHQxWbPlPSrVe2Me8zHNH7Fk3NZj0LH30g6e650LTExILvah03ICBa+uRb3LP9vqG+rsKjC2Uk8rlcBOHp0HAQRKGHzD04Mtk/TaH3xazRpcJlbKRpbvTjv8vgjInYr/dyss7hHW2h4x5TVj1jN9TDk6unmwTZcUfzsW0ox9E7hE0Pcg1r4HBkSRBCIcQjU7/5TPb/hLheN1Xx34/q+IjPdx5Pn05gytNb+OQKeKV/AsiWNOs2mEt1NBcxk6lyG2s71rC2Yx7V7OYyNkIj3Mi/0H9rZYK6+ylSysaCfUfpUiYulH5yERbnVpl/gij0HrnGr0+EL0sVREPqTsTY4m244UM/FD6urKDyxH7GfLCVK2Q863Qrk2nna3JbRrVquh64FQ7UV3B85+fR8MJVoD8R5IVD0C5RLxsv6mbcdHvlLPBBGcU7F8oCEZQOLiWCPArL1sMjzeM+Y4DAt9x5FdNWb4isen2tcjSn8yayTunqPpvlHUpX57jI4ali2jR9A27WCpOU+wdQU9/NTdzP6IZXB8SQv+qDFqbVPTUgv+pAT5t8C3xQ52ZSEc7ffxmKfK4XVzg7OtgE+Qefy0RgomNjTB/1sODOlTQ2r6GtdRZbG8cwbcYG2pnM3sl1RnDXSyTP7FPM5Cydxrf6uwGTaHuSThh0liYbAnAbY5HqQ/R01rKms5Gu5nFRQd8Ja5vnsYeRbL7zfLPi1rPH5xqFMy5hteOH93dfhuYayI+JwJluCkOpmW+SHWfNNiOBf8Yky/Y8XDDv62cKl3eoyUxF9PNlM4XlHQrVSnXde1wvdQnP/pUu5pcHb6f/wcqouPtH6v7E4V66w6uJSdQBwYo7U+4Cn8fMUKVJPib9XDCzwhDUCVnIvm6JJmftRGwvRlS9idedREw2B3UOtDAw/+pOWH67wk54suEiRtDHCwnO3HQGTOcc+nuPixbGiryXu7YaczPZSZ5H8U7gi0kZmmvySfgvgGBSiuabRMd+EhXUGJt49YzdNN6xxghvb/zX7JZNXHTwGU7WOfFP2QDjecVsx/OB7yEaz74HE7cmEoUy11F8WG3vHqXx+y5jkc/XxVcaF0LwCLI4FMBs8RkDxb6KwUm244UesKI9kj0s+2jgRzdrBVc92MJWzkFXDDO+8P7v8CZYY1+DzDTZUKj+G6rronR+12Vqk/fIp1nAmW4KQ1BNN5Bb3WKP9fnP+10rY6km4mJZvXo3Z7Mt8tEeRjKb9RwmPwfgTODqvo/o31HJtIYNtLXOippj4iUmH2CiyWUU7wS+8DgXyjTJ50UThgsjjAT5kT+fI3qfqHqj+nijd58499xRS1vzLEbQR1vrLLo6x3E222j6Nlyj1dyk3fTvqIQOaGuZFfc7BpwzZwrZV07gs6VMJ14LhZuMLRxBnZDNpV6xx8asiPUnAvcnAe/xbdfD2u65kRDBs3s3oQuFx6SHnl2jouYeL4Sw9+5nkMBnY6oppAg7gc8FJ/J5Fw8n9IWjHIQ+Dv60gbEj8A6g1z61VwFnKDV13ez9ZR2/r3ueLT1TIv712dcvH/sEndIUeEjDXCMi3xSR50WkS0TeFJFbbHmliDwrIu/a9+NsuYjIfSKyS0TeEJFxvu+61u7/rohcW7hmFZvSvWCKTykISiz+NqU5iva8cGDg5Gy78OGBOu66bTHvMZKWhqsGHhNLzqP4QvfHUPR3af9e07HJfwncpqqjgfOAG0VkDLAI2KyqpwKb7d8A04BT7es64AEwNwVgGfA3wLnAMu/GUHwKcSHtp9QvnuIRRDt9PusTR2jTsZlbs8ywp5RVzKens5bG5jV5rFcsTuDDQEqRV9W9qvqq3f4U6AJOBGYAv7G7/YboWrkZwGNq+AMwQkRqgO8Cz6rqAVX9GHgW+F5eWxNISv8iKh6lJPRJJmKTES8zYC8mo1Qy4saMz2QUH3aBL59BWEbeNSIyEjgbeAn4uqruBXMjIGqIPhH4H99h79uyROXxznOdiLwiIq/A/2ZSxRwo5EVVHhdTcSgloU9Buh4wVVBd9x4LGlYy+s5Xo4ugMs7bmqgtpSDw5UPaIi8iRwNPAreqarJbfjzfTU1SPrhQ9WFVPUdVz4G/TLeKAae8LqyhJWjmm3xlN8rQPm6FfHPj+fS01vJA80K6OsdRfeduWKomlLEX9TJrnMCHjbS8a0TkcIzA/1ZVN9jifSJSo6p7rTnG+++9D3zTd/hJwIe2fHJMeXv2VS8EhfbecJ43hSVI3jf5qkuCRCOx1GNEHJja+WLUo6YXenbWGnGfaMv8Acl2kIGPvBP4MJKOd41gQiR1qepK30dPA56HzLVAq6/8Gutlcx5w0Jpz/gv4jogcZydcv2PLyozysQUWhyCN6LMh+/pXTD7Aghkr6W6oiXrcdGBWudoolveu+BHL5ouZQVuEEf+j431bbD2cwIeVdEbyDcAPgO0i4q2hXgL8AlgnIo3An4Dv2882AdOBXRiD+lwAVT0gIv8I/NHu91NVPZCXVuSVoRoNulF94cg0hV+hKOBo3rOvV0e3LxjezjbGUjd370AXS49euG3ur2HVr6OLovy5XBOO6MMs8OUr7h4hiF0jnwJvF7seeaaKHJanBBTXpnDg2hQOUrXpr1X1hHS+KAwrXt82E7Clg4i84toUfFybwoFrU3LKPECZw+FwlDZO5B0Oh6OECYPIP1zsChQA16Zw4NoUDlybkhD4iVeHw+FwZE8YRvIOh8PhyBIn8g6Hw1HCBFbkReR7IvK2jUu/KPURwUFE9ojIdhHZZoKsZRd/v5iIyCMisl9EdvjKQp1DIEGbmkTkA9tX20Rkuu+zxbZNb4vId33lgbk2SzHfQ5I2hbavRKRCRF4Wkddtm5bb8lEi8pL9nz8hIkfY8iPt37vs5yN93xW3rQlR1cC9gMOAbqAWOAJ4HRhT7HplUP89QFVM2T8Bi+z2IqDZbk8H2jAB3M4DXip2/W29JgHjgB3ZtgGoBHbb9+Ps9nEBa1MTcHucfcfY6+5IYJS9Hg8L2rUJ1ADj7PYxwDu27qHtqyRtCm1f2f/30Xb7cEwk3/OAdcCVtvxBYIHd/hHwoN2+EngiWVuTnTuoI/lzgV2qultV/w94HBOnPsxkGn+/qKjqC0Bs2IlQ5xBI0KZEzAAeV9UvVPU9TJiOcwnYtaklmO8hSZsSEfi+sv9vL3DE4falwBRgvS2P7Sev/9YDU0VESNzWhARV5NOOPR9QFPi9iGwVketsWabx94NIwXIIFJmbrOniEYlmKwtdm2SI8j0MJTFtghD3lYgcJib+137MTbQb6FPVL+PUL1J3+/lB4HiyaFNQRT7t2PMBpUFVx2FSId4oIpOS7Bv2tkIecggUkQeAOmAssBe415aHqk0yhPkehoo4bQp1X6nqV6o6FhNm/VxgdLzd7Hve2hRUkU8Ukz4UqOqH9n0/8BSmQ/d5ZhhJL/5+EMm0DYFvm6rusz++Q8C/En30DU2bJEm+B/t56PoqXptKoa8AigXRkQAAAVZJREFUVLUPk0vjPIy5zIsh5q9fpO728+EYU2PGbQqqyP8RONXOPB+BmXh4ush1SgsR+SsROcbbxsTN30Hm8feDSMnlEIiZ/7gM01dg2nSl9XIYhUlM/zIBuzatnbak8j0kalOY+0pEThCREXb7KOBCzFzD88DldrfYfvL673LgOTUzr4namphizDSnORs9HTOr3g38uNj1yaDetZjZ79eBN726Y+xpm4F37XulRmfd77ft3A6cU+w22HqtxTwS/xkzemjMpg3APMzk0C5gbgDb9G+2zm/YH1CNb/8f2za9DUwL4rWJyfektv7b7Gt6mPsqSZtC21fAWcBrtu47gJ/Y8lqMSO8C/gM40pZX2L932c9rU7U10cuFNXA4HI4SJqjmGofD4XDkASfyDofDUcI4kXc4HI4Sxom8w+FwlDBO5B0Oh6OEcSLvcDgcJYwTeYfD4Shh/h8f7bX+7Po9fAAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%time\n", "\n", "h, w = 2048, 3072\n", "gimage = np.zeros((h, w), dtype=np.uint8)\n", "xmin, xmax, ymin, ymax = np.array([-2.0, 1.0, -1.0, 1.0]).astype('float32')\n", "iters = 50\n", "create_fractal_cython_par(xmin, xmax, ymin, ymax, gimage, iters)\n", "plt.imshow(gimage, cmap='jet')\n", "pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parallelism using `ipyparallel`" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from ipyparallel import Client" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 2, 3]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rc = Client()\n", "rc.ids" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "dv = rc[:]" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "@dv.parallel(block=True)\n", "@jit(nopython=True, cache=True)\n", "def mandel(x, y, max_iters):\n", " c = complex(x, y)\n", " z = 0\n", " for i in range(max_iters):\n", " z = z*z + c\n", " if z.real * z.real + z.imag * z.imag >= 4: # abs(z) >= 4:\n", " return i\n", " return max_iters" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "# @jit(nopython=True, cache=True)\n", "def create_fractal(xmin, xmax, ymin, ymax, image, iters):\n", " height, width = image.shape\n", "\n", " pixel_size_x = (xmax - xmin)/width\n", " pixel_size_y = (ymax - ymin)/height\n", "\n", " args = [] \n", " for x in range(width):\n", " real = xmin + x*pixel_size_x\n", " for y in range(height):\n", " imag = ymin + y*pixel_size_y\n", " args.append((real, imag, iters)) \n", " \n", " colors = np.array(mandel(np.array(args).T), 'float') \n", " return colors.reshape((width, height)).T" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "ename": "KeyboardInterrupt", "evalue": "", "output_type": "error", "traceback": [ "\u001b[0;31m\u001b[0m", "\u001b[0;31mTimeoutError\u001b[0mTraceback (most recent call last)", "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/ipyparallel/client/asyncresult.py\u001b[0m in \u001b[0;36m_ordered_iter\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 688\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 689\u001b[0;31m \u001b[0mrlist\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 690\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTimeoutError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/ipyparallel/client/asyncresult.py\u001b[0m in \u001b[0;36mget\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 170\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 171\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTimeoutError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Result not ready.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 172\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTimeoutError\u001b[0m: Result not ready.", "\nDuring handling of the above exception, another exception occurred:\n", "\u001b[0;31mKeyboardInterrupt\u001b[0mTraceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n", "\u001b[0;32m\u001b[0m in \u001b[0;36mcreate_fractal\u001b[0;34m(xmin, xmax, ymin, ymax, image, iters)\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreal\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mimag\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0miters\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0mcolors\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmandel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mT\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'float'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mcolors\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidth\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mheight\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mT\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/ipyparallel/client/asyncresult.py\u001b[0m in \u001b[0;36m__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 668\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__iter__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 669\u001b[0m \u001b[0mit\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_ordered_iter\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mordered\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_unordered_iter\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 670\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 671\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 672\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/ipyparallel/client/asyncresult.py\u001b[0m in \u001b[0;36m_ordered_iter\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 692\u001b[0m \u001b[0mevt\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mEvent\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 693\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mchild\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_children\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 694\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_wait_for_child\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchild\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mevt\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mevt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 695\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_yield_child_results\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchild\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 696\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/ipyparallel/client/asyncresult.py\u001b[0m in \u001b[0;36m_wait_for_child\u001b[0;34m(child, evt, timeout)\u001b[0m\n\u001b[1;32m 380\u001b[0m \u001b[0mevt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclear\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 381\u001b[0m \u001b[0mchild\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_done_callback\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mevt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 382\u001b[0;31m \u001b[0mevt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 383\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 384\u001b[0m \u001b[0;31m# asynchronous iterator:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/conda/lib/python3.6/threading.py\u001b[0m in \u001b[0;36mwait\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 549\u001b[0m \u001b[0msignaled\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_flag\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 550\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0msignaled\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 551\u001b[0;31m \u001b[0msignaled\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_cond\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 552\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0msignaled\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 553\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/conda/lib/python3.6/threading.py\u001b[0m in \u001b[0;36mwait\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 297\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 298\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mtimeout\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 299\u001b[0;31m \u001b[0mgotit\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mwaiter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0macquire\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 300\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 301\u001b[0m \u001b[0mgotit\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mwaiter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0macquire\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mKeyboardInterrupt\u001b[0m: " ] } ], "source": [ "%%time\n", "\n", "h, w = 2048//4, 3072//4\n", "gimage = np.zeros((h, w), dtype=np.uint8)\n", "xmin, xmax, ymin, ymax = np.array([-2.0, 1.0, -1.0, 1.0]).astype('float32')\n", "iters = 50\n", "gimage = create_fractal(xmin, xmax, ymin, ymax, gimage, iters)\n", "plt.imshow(gimage, cmap='jet')\n", "pass" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "mandel.map?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "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.6.3" } }, "nbformat": 4, "nbformat_minor": 2 }