Skip to content
Snippets Groups Projects
test_basic_usage_llvm.ipynb 22.6 KiB
Newer Older
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# pystencils - LLVM generation\n",
    "The generation of LLVM code is simliar but not identical as seen with the C++ version. For the generation itself a python module ``llvmlite`` is used. This module provides the necessary support and bindings for LLVM. In order to generate from the AST to llvm, the AST needs to be transformed to support type conversions. This is the biggest difference to the C++ version. C++ doesn't need that since the language itself handles the casts.\n",
    "\n",
    "In this example a simple weighted Jacobi kernel is generated, so the focus remains on the part of LLVM generation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sympy as sp\n",
    "import numpy as np\n",
    "import ctypes\n",
    "from pystencils import Field, Assignment\n",
    "from pystencils import create_kernel\n",
    "from pystencils.display_utils import to_dot\n",
    "\n",
    "sp.init_printing()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The numpy arrays (with inital values) create *Field*s for the update Rule. Later those arrays are used for the computation itself."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "src_arr = np.zeros((30, 20))\n",
    "src_arr[0,:] = 1.0\n",
    "src_arr[:,0] = 1.0\n",
    "dst_arr = src_arr.copy()\n",
    "\n",
    "src_field = Field.create_from_numpy_array('src', src_arr)\n",
    "dst_field = Field.create_from_numpy_array('dst', dst_arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using the *Field* objects and the additional *Symbol* $\\omega$ for the weight the update rule is specified as a *sympy* equation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "                            ω⋅(src_E + src_N + src_S + src_W)\n",
       "dst_C := src_C⋅(-ω + 1.0) + ─────────────────────────────────\n",
       "                                            4                "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "omega = sp.symbols(\"omega\")\n",
    "update_rule = Assignment(dst_field[0,0], omega * (src_field[0,1] + src_field[0,-1] + src_field[1,0] + src_field[-1,0]) / 4\n",
    "                   + (1.-omega)*src_field[0,0])\n",
    "update_rule"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With this update rule an abstract syntax tree (AST) can be created. This AST can be used to print the LLVM code. The creation follows the same routines as the C++ version does. However at the end there are two more steps. In order to generate LLVM, type casting and pointer arithmetic had to be introduced (which C++ does for you)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "KernelFunction kernel([<double * RESTRICT fd_dst>, <double * RESTRICT const fd_src>, <double omega>])\n",
      "\tBlock for(ctr_0=1; ctr_0<29; ctr_0+=1)\n",
      "\t\tBlock fd_dst_C ← pointer_arithmetic_func(fd_dst, 20*ctr_0)\n",
      "\t\tfd_src_C ← pointer_arithmetic_func(fd_src, 20*ctr_0)\n",
      "\t\tfd_src_E ← pointer_arithmetic_func(fd_src, 20*ctr_0 + 20)\n",
      "\t\tfd_src_W ← pointer_arithmetic_func(fd_src, 20*ctr_0 - 20)\n",
      "\t\tfor(ctr_1=1; ctr_1<19; ctr_1+=1)\n",
      "\t\t\tBlock fd_dst_C[ctr_1] ← omega*(fd_src_C[ctr_1 + 1] + fd_src_C[ctr_1 - 1] + fd_src_E[ctr_1] + fd_src_W[ctr_1])/4 + (omega*cast_func(-1, double) + 1.0)*fd_src_C[ctr_1]\n",
      "\t\t\n",
      "\t\n",
      "\n"
     ]
    }
   ],
   "source": [
    "ast = create_kernel([update_rule], target='llvm')\n",
    "print(str(ast))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is possible to examine the AST further."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.38.0 (20140413.2041)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"570pt\" height=\"476pt\"\n",
       " viewBox=\"0.00 0.00 569.74 476.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 472)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-472 565.74,-472 565.74,4 -4,4\"/>\n",
       "<!-- 139831602112104 -->\n",
       "<g id=\"node1\" class=\"node\"><title>139831602112104</title>\n",
       "<ellipse fill=\"#a056db\" stroke=\"black\" cx=\"249.896\" cy=\"-450\" rx=\"112.38\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"249.896\" y=\"-446.3\" font-family=\"Times,serif\" font-size=\"14.00\">Func: kernel (dst,src,omega)</text>\n",
       "</g>\n",
       "<!-- 139831601760856 -->\n",
       "<g id=\"node11\" class=\"node\"><title>139831601760856</title>\n",
       "<ellipse fill=\"#dbc256\" stroke=\"black\" cx=\"249.896\" cy=\"-378\" rx=\"31.6951\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"249.896\" y=\"-374.3\" font-family=\"Times,serif\" font-size=\"14.00\">Block</text>\n",
       "</g>\n",
       "<!-- 139831602112104&#45;&gt;139831601760856 -->\n",
       "<g id=\"edge10\" class=\"edge\"><title>139831602112104&#45;&gt;139831601760856</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M249.896,-431.697C249.896,-423.983 249.896,-414.712 249.896,-406.112\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"253.396,-406.104 249.896,-396.104 246.396,-406.104 253.396,-406.104\"/>\n",
       "</g>\n",
       "<!-- 139831601760688 -->\n",
       "<g id=\"node2\" class=\"node\"><title>139831601760688</title>\n",
       "<ellipse fill=\"#3498db\" stroke=\"black\" cx=\"249.896\" cy=\"-306\" rx=\"70.6878\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"249.896\" y=\"-302.3\" font-family=\"Times,serif\" font-size=\"14.00\">Loop over dim 0</text>\n",
       "</g>\n",
       "<!-- 139831601760296 -->\n",
       "<g id=\"node10\" class=\"node\"><title>139831601760296</title>\n",
       "<ellipse fill=\"#dbc256\" stroke=\"black\" cx=\"249.896\" cy=\"-234\" rx=\"31.6951\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"249.896\" y=\"-230.3\" font-family=\"Times,serif\" font-size=\"14.00\">Block</text>\n",
       "</g>\n",
       "<!-- 139831601760688&#45;&gt;139831601760296 -->\n",
       "<g id=\"edge8\" class=\"edge\"><title>139831601760688&#45;&gt;139831601760296</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M249.896,-287.697C249.896,-279.983 249.896,-270.712 249.896,-262.112\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"253.396,-262.104 249.896,-252.104 246.396,-262.104 253.396,-262.104\"/>\n",
       "</g>\n",
       "<!-- 139832610576760 -->\n",
       "<g id=\"node3\" class=\"node\"><title>139832610576760</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"black\" cx=\"42.8962\" cy=\"-162\" rx=\"42.7926\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"42.8962\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">fd_dst_C</text>\n",
       "</g>\n",
       "<!-- 139832610531536 -->\n",
       "<g id=\"node4\" class=\"node\"><title>139832610531536</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"black\" cx=\"146.896\" cy=\"-162\" rx=\"42.7926\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"146.896\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">fd_src_C</text>\n",
       "</g>\n",
       "<!-- 139831601689544 -->\n",
       "<g id=\"node5\" class=\"node\"><title>139831601689544</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"black\" cx=\"249.896\" cy=\"-162\" rx=\"42.4939\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"249.896\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">fd_src_E</text>\n",
       "</g>\n",
       "<!-- 139831601689432 -->\n",
       "<g id=\"node6\" class=\"node\"><title>139831601689432</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"black\" cx=\"355.896\" cy=\"-162\" rx=\"46.2923\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"355.896\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">fd_src_W</text>\n",
       "</g>\n",
       "<!-- 139831601761472 -->\n",
       "<g id=\"node7\" class=\"node\"><title>139831601761472</title>\n",
       "<ellipse fill=\"#3498db\" stroke=\"black\" cx=\"490.896\" cy=\"-162\" rx=\"70.6878\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"490.896\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">Loop over dim 1</text>\n",
       "</g>\n",
       "<!-- 139831601761360 -->\n",
       "<g id=\"node9\" class=\"node\"><title>139831601761360</title>\n",
       "<ellipse fill=\"#dbc256\" stroke=\"black\" cx=\"490.896\" cy=\"-90\" rx=\"31.6951\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"490.896\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">Block</text>\n",
       "</g>\n",
       "<!-- 139831601761472&#45;&gt;139831601761360 -->\n",
       "<g id=\"edge2\" class=\"edge\"><title>139831601761472&#45;&gt;139831601761360</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M490.896,-143.697C490.896,-135.983 490.896,-126.712 490.896,-118.112\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"494.396,-118.104 490.896,-108.104 487.396,-118.104 494.396,-118.104\"/>\n",
       "</g>\n",
       "<!-- 139831601222656 -->\n",
       "<g id=\"node8\" class=\"node\"><title>139831601222656</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"black\" cx=\"490.896\" cy=\"-18\" rx=\"66.8882\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"490.896\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">fd_dst_C[ctr_1]</text>\n",
       "</g>\n",
       "<!-- 139831601761360&#45;&gt;139831601222656 -->\n",
       "<g id=\"edge1\" class=\"edge\"><title>139831601761360&#45;&gt;139831601222656</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M490.896,-71.6966C490.896,-63.9827 490.896,-54.7125 490.896,-46.1124\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"494.396,-46.1043 490.896,-36.1043 487.396,-46.1044 494.396,-46.1043\"/>\n",
       "</g>\n",
       "<!-- 139831601760296&#45;&gt;139832610576760 -->\n",
       "<g id=\"edge3\" class=\"edge\"><title>139831601760296&#45;&gt;139832610576760</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M223.258,-223.992C188.18,-212.13 126.117,-191.142 84.7403,-177.15\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"85.8067,-173.816 75.2124,-173.928 83.5642,-180.447 85.8067,-173.816\"/>\n",
       "</g>\n",
       "<!-- 139831601760296&#45;&gt;139832610531536 -->\n",
       "<g id=\"edge4\" class=\"edge\"><title>139831601760296&#45;&gt;139832610531536</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M230.037,-219.503C215.003,-209.286 194.096,-195.077 177.009,-183.465\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"178.711,-180.39 168.473,-177.664 174.776,-186.179 178.711,-180.39\"/>\n",
       "</g>\n",
       "<!-- 139831601760296&#45;&gt;139831601689544 -->\n",
       "<g id=\"edge5\" class=\"edge\"><title>139831601760296&#45;&gt;139831601689544</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M249.896,-215.697C249.896,-207.983 249.896,-198.712 249.896,-190.112\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"253.396,-190.104 249.896,-180.104 246.396,-190.104 253.396,-190.104\"/>\n",
       "</g>\n",
       "<!-- 139831601760296&#45;&gt;139831601689432 -->\n",
       "<g id=\"edge6\" class=\"edge\"><title>139831601760296&#45;&gt;139831601689432</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M269.834,-219.834C285.399,-209.555 307.297,-195.094 325.109,-183.331\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"327.063,-186.235 333.479,-177.804 323.206,-180.394 327.063,-186.235\"/>\n",
       "</g>\n",
       "<!-- 139831601760296&#45;&gt;139831601761472 -->\n",
       "<g id=\"edge7\" class=\"edge\"><title>139831601760296&#45;&gt;139831601761472</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M277.542,-224.97C316.06,-213.782 386.695,-193.266 436.102,-178.915\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"437.367,-182.193 445.994,-176.042 435.415,-175.47 437.367,-182.193\"/>\n",
       "</g>\n",
       "<!-- 139831601760856&#45;&gt;139831601760688 -->\n",
       "<g id=\"edge9\" class=\"edge\"><title>139831601760856&#45;&gt;139831601760688</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M249.896,-359.697C249.896,-351.983 249.896,-342.712 249.896,-334.112\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"253.396,-334.104 249.896,-324.104 246.396,-334.104 253.396,-334.104\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.files.Source at 0x7f2d14f276a0>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "to_dot(ast)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With transformed AST it is now possible to generate and compile the AST into LLVM. Notice that unlike in C++ version, no files are writen to the hard drive (although it is possible).\n",
    "\n",
    "There are multiple ways how to generate and compile the AST. The most simple one is simillar to the C++ version. Using the ``compile()`` function of the generated AST\n",
    "\n",
    "You can also manually create a python function with ``make_python_function``.\n",
    "\n",
    "Another option is obtaining the jit itself with ``generate_and_jit``.\n",
    "The function ``generate_and_jit`` first generates and the compiles the AST.\n",
    "\n",
    "If even more controll is needed, it is possible to use the functions ``generateLLVM`` and ``compileLLVM`` to achieve the same. For further controll, instead of calling ``compileLLVM`` the jit object itself can be created and its necessary functions for the compilation have to be run manually (``parse``, (``optimize``,) ``compile``)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "kernel = ast.compile()\n",
    "\n",
    "#kernel = make_python_function(ast)\n",
    "\n",
    "# Or alternativally\n",
    "#jit = generate_and_jit(ast)\n",
    "# Call: jit('kernel', src_arr, dst_arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The compiled function(s) can be used now. Either call the function (with arguments, if not given before) or call the jit object with the function's name and its arguments. Here, numpy arrays are automatically adjusted with ctypes.\n",
    "\n",
    "The functions and arguments can be read as well.\n",
    "\n",
    "**All of the information the jit object has comes from the module which was parsed. If you parse a second module and don't run the compilation step, the module and the compiled code are not the same anymore, thus leading to false information**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#jit.print_functions()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "for i in range(100):\n",
    "    kernel(src=src_arr, dst=dst_arr, omega=2/3)\n",
    "    src_arr, dst_arr = dst_arr, src_arr\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The output is drawn with matplotlib."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import cm\n",
    "fig = plt.figure()\n",
    "ax = fig.add_subplot(111)\n",
    "ax.imshow(dst_arr, cmap=cm.jet)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "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.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}