Skip to content

Instantly share code, notes, and snippets.

@willirath
Created February 22, 2019 08:44
Show Gist options
  • Save willirath/413972396b1f1b81061b2940d488e059 to your computer and use it in GitHub Desktop.
Save willirath/413972396b1f1b81061b2940d488e059 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"!rm *.prof"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Line profiling with MPI"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## A script where rank 0 broadcasts random numbers"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Overwriting script_with_mpi_and_profiling.py\n"
]
}
],
"source": [
"%%file script_with_mpi_and_profiling.py\n",
"\n",
"from mpi4py import MPI\n",
"import numpy as np\n",
"import cProfile as profile\n",
"\n",
"\n",
"def broadcast_random_numbers(size=int(1e9 / 8), iter=1):\n",
" \"\"\"Broadcast random numbers.\n",
"\n",
" Parameters\n",
" ----------\n",
"\n",
" size (integer) : Size in Bytes. Defaults to `1e9/8` which is \"1GB\".\n",
"\n",
" \"\"\"\n",
"\n",
" # Where am I in the MPI cluster?\n",
" comm = MPI.COMM_WORLD\n",
" rank = comm.Get_rank()\n",
"\n",
" for niter in range(iter):\n",
" # If on master node (rank=0), create real data\n",
" # if not, just allocate memory\n",
" if rank == 0:\n",
" data = np.random.uniform(0, 1, (size, )).astype('d')\n",
" else:\n",
" data = np.empty((size, ), dtype='d')\n",
"\n",
" # let rank 0 broad cast real data to all others\n",
" comm.Bcast(data, root=0)\n",
"\n",
"# create output file for each member and run profiler\n",
"output_file = \"_profile_{:04d}_of_{:04d}.prof\".format(MPI.COMM_WORLD.rank,\n",
" MPI.COMM_WORLD.size - 1)\n",
"profile.run('broadcast_random_numbers(iter=20)', filename=output_file)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Run with MPI"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"!mpiexec -n 4 python script_with_mpi.py"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Collect and combine all profiles"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"from pstats import Stats\n",
"\n",
"# get all profiles\n",
"profiles = tuple(map(str, sorted(Path(\".\").glob(\"_profile*.prof\"))))\n",
"\n",
"# collect in one big stats object and dump to disk\n",
"stat = Stats()\n",
"stat.add(*profiles)\n",
"stat.dump_stats(\"profile_collected.prof\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Read combined profile into a pandas dataframe"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from pstats import Stats\n",
"import pandas as pd"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def prof_to_df(filename):\n",
" \n",
" stat = Stats(filename)\n",
" \n",
" df = pd.DataFrame.from_dict(stat.stats)\n",
" \n",
" df = df.transpose()\n",
" df = df.reset_index()\n",
" \n",
" df.columns = [\"callee_path\", \"callee_line\", \"callee_func\",\n",
" \"ncalls_prim\", \"ncalls_rec\", \"tottime\", \"cumtime\",\n",
" \"callers\"]\n",
" \n",
" df[\"callers\"] = df[\"callers\"].apply(str)\n",
" df[\"filename\"] = filename\n",
" \n",
" return df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Let's have a look"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>callee_path</th>\n",
" <th>callee_line</th>\n",
" <th>callee_func</th>\n",
" <th>ncalls_prim</th>\n",
" <th>ncalls_rec</th>\n",
" <th>tottime</th>\n",
" <th>cumtime</th>\n",
" <th>callers</th>\n",
" <th>filename</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>~</td>\n",
" <td>0</td>\n",
" <td>&lt;built-in method builtins.exec&gt;</td>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" <td>0.00019</td>\n",
" <td>220.459</td>\n",
" <td>{}</td>\n",
" <td>profile_collected.prof</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>~</td>\n",
" <td>0</td>\n",
" <td>&lt;method 'disable' of '_lsprof.Profiler' objects&gt;</td>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" <td>3e-06</td>\n",
" <td>3e-06</td>\n",
" <td>{}</td>\n",
" <td>profile_collected.prof</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>&lt;string&gt;</td>\n",
" <td>1</td>\n",
" <td>&lt;module&gt;</td>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" <td>0.231074</td>\n",
" <td>220.459</td>\n",
" <td>{('~', 0, '&lt;built-in method builtins.exec&gt;'): ...</td>\n",
" <td>profile_collected.prof</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>~</td>\n",
" <td>0</td>\n",
" <td>&lt;built-in method numpy.core.multiarray.empty&gt;</td>\n",
" <td>60</td>\n",
" <td>60</td>\n",
" <td>0.001346</td>\n",
" <td>0.001346</td>\n",
" <td>{('script_with_mpi.py', 6, 'broadcast_random_n...</td>\n",
" <td>profile_collected.prof</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>~</td>\n",
" <td>0</td>\n",
" <td>&lt;method 'Get_rank' of 'mpi4py.MPI.Comm' objects&gt;</td>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" <td>5e-06</td>\n",
" <td>5e-06</td>\n",
" <td>{('script_with_mpi.py', 6, 'broadcast_random_n...</td>\n",
" <td>profile_collected.prof</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>~</td>\n",
" <td>0</td>\n",
" <td>&lt;method 'Bcast' of 'mpi4py.MPI.Comm' objects&gt;</td>\n",
" <td>80</td>\n",
" <td>80</td>\n",
" <td>178.364</td>\n",
" <td>178.364</td>\n",
" <td>{('script_with_mpi.py', 6, 'broadcast_random_n...</td>\n",
" <td>profile_collected.prof</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>script_with_mpi.py</td>\n",
" <td>6</td>\n",
" <td>broadcast_random_numbers</td>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" <td>4.69829</td>\n",
" <td>220.228</td>\n",
" <td>{('&lt;string&gt;', 1, '&lt;module&gt;'): (4, 4, 4.6982909...</td>\n",
" <td>profile_collected.prof</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>~</td>\n",
" <td>0</td>\n",
" <td>&lt;method 'uniform' of 'mtrand.RandomState' obje...</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>34.2681</td>\n",
" <td>34.2681</td>\n",
" <td>{('script_with_mpi.py', 6, 'broadcast_random_n...</td>\n",
" <td>profile_collected.prof</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>~</td>\n",
" <td>0</td>\n",
" <td>&lt;method 'astype' of 'numpy.ndarray' objects&gt;</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>2.89564</td>\n",
" <td>2.89564</td>\n",
" <td>{('script_with_mpi.py', 6, 'broadcast_random_n...</td>\n",
" <td>profile_collected.prof</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" callee_path callee_line \\\n",
"0 ~ 0 \n",
"1 ~ 0 \n",
"2 <string> 1 \n",
"3 ~ 0 \n",
"4 ~ 0 \n",
"5 ~ 0 \n",
"6 script_with_mpi.py 6 \n",
"7 ~ 0 \n",
"8 ~ 0 \n",
"\n",
" callee_func ncalls_prim ncalls_rec \\\n",
"0 <built-in method builtins.exec> 4 4 \n",
"1 <method 'disable' of '_lsprof.Profiler' objects> 4 4 \n",
"2 <module> 4 4 \n",
"3 <built-in method numpy.core.multiarray.empty> 60 60 \n",
"4 <method 'Get_rank' of 'mpi4py.MPI.Comm' objects> 4 4 \n",
"5 <method 'Bcast' of 'mpi4py.MPI.Comm' objects> 80 80 \n",
"6 broadcast_random_numbers 4 4 \n",
"7 <method 'uniform' of 'mtrand.RandomState' obje... 20 20 \n",
"8 <method 'astype' of 'numpy.ndarray' objects> 20 20 \n",
"\n",
" tottime cumtime callers \\\n",
"0 0.00019 220.459 {} \n",
"1 3e-06 3e-06 {} \n",
"2 0.231074 220.459 {('~', 0, '<built-in method builtins.exec>'): ... \n",
"3 0.001346 0.001346 {('script_with_mpi.py', 6, 'broadcast_random_n... \n",
"4 5e-06 5e-06 {('script_with_mpi.py', 6, 'broadcast_random_n... \n",
"5 178.364 178.364 {('script_with_mpi.py', 6, 'broadcast_random_n... \n",
"6 4.69829 220.228 {('<string>', 1, '<module>'): (4, 4, 4.6982909... \n",
"7 34.2681 34.2681 {('script_with_mpi.py', 6, 'broadcast_random_n... \n",
"8 2.89564 2.89564 {('script_with_mpi.py', 6, 'broadcast_random_n... \n",
"\n",
" filename \n",
"0 profile_collected.prof \n",
"1 profile_collected.prof \n",
"2 profile_collected.prof \n",
"3 profile_collected.prof \n",
"4 profile_collected.prof \n",
"5 profile_collected.prof \n",
"6 profile_collected.prof \n",
"7 profile_collected.prof \n",
"8 profile_collected.prof "
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"profile_df = prof_to_df(\"profile_collected.prof\")\n",
"profile_df"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.axes._subplots.AxesSubplot at 0x7f6f40313518>"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAIPCAYAAAB9pxV/AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzsnXeYVdXV/z9fkIgFLIDKT4wgrwWVIlIjloiCFWMhWAM2NJrEaGIsSSxE8xpjTLCiURFr7IqJRkQsQVBBHEHALirqq4gNo6Lg+v2x9525MwwzA8zcfe5xfZ5nnnvPvuV8595z19ln7VVkZjiO4zj5pVlqAY7jOE7T4obecRwn57ihdxzHyTlu6B3HcXKOG3rHcZyc44becRwn57ihdxzHyTlu6B3HcXKOG3rHcZycs1pqAQBt27a1jh07ppbhOI5TVjz77LMfmlm7+p6XCUPfsWNHpk+fnlqG4zhOWSHpzYY8z103juM4OccNveM4Ts5xQ+84jpNzMuGjdxynvPjmm2+YP38+X331VWop3wlatmxJhw4daNGixUq93g294zgrzPz582nVqhUdO3ZEUmo5ucbMWLhwIfPnz6dTp04r9R7uunEcZ4X56quvaNOmjRv5EiCJNm3arNLVkxt6x3FWCjfypWNVP2s39I7jODnnO+Gjv/z4SdW2TxyzayIl2cc/K2dl6Hj6vxr1/eZdsHejvt93HZ/RO46Te66//np+9rOfAXDOOedw0UUXNcl7jxkzhhtuuKHR3rux+E7M6B3HcUrB8ccfn1pCrfiM3nGcsuWGG26gW7dudO/enSOOOIL777+fvn37st1227Hbbrvx/vvv1/n61157jT322IPtt9+eHXfckRdffBGABQsWcOCBB9K7d2969+7Nk08+2SA9xVcLu+yyC6eddhp9+vRhiy224D//+Q8AS5cu5dRTT6V3795069aNq666ahU+gYbhM3rHccqS2bNnc/755/Pkk0/Stm1bPvroIyTx1FNPIYlrrrmGCy+8kL/85S/LfY+RI0cyZswYNt98c55++mlOOOEEJk2axEknncTJJ5/MgAEDeOuttxg8eDBz585dYY1LlizhmWee4YEHHuDcc89l4sSJXHvttayzzjpMmzaNxYsXs8MOOzBo0KCVjpFvCG7oHccpSyZNmsRBBx1E27ZtAVh//fWZNWsWw4YN47333uPrr7+u03h+/vnnTJkyhaFDh1aOLV68GICJEycyZ86cyvHPPvuMRYsW0apVqxXSeMABBwCw/fbbM2/ePAAmTJjAzJkzufPOOwH49NNPeeWVV9zQO47j1MTMlokv//nPf84pp5zCkCFDeOyxxzjnnHOW+/pvv/2Wddddl4qKilofmzp1KmusscYqaVx99dUBaN68OUuWLKnUfemllzJ48OBVeu8VwQ294zirTF3hkB+8+Vnl/Q02bd1o+xw4cCD7778/J598Mm3atOGjjz7i008/ZeONNwZg3Lhxdb6+devWdOrUiTvuuIOhQ4diZsycOZPu3bszaNAgLrvsMk499VQAKioq6NGjR6PoHjx4MFdeeSW77rorLVq04OWXX2bjjTdmrbXWapT3rw1fjHUcpyzZZptt+O1vf8vOO+9M9+7dOeWUUzjnnHMYOnQoO+64Y6VLpy5uvvlmrr32Wrp3784222zDfffdB8All1zC9OnT6datG1tvvTVjxoxpNN3HHHMMW2+9NT179mTbbbfluOOOq5ztNxUysybdQUPo1auXNWWHKU8Cajj+WTkNYe7cuXTp0qVBz22qGf13jdo+c0nPmlmv+l7rM3rHcZyc4z56x3GcBjB27FhGjx5dbWyHHXbg8ssvT6So4bihdxzHaQBHHnkkRx55ZGoZK4W7bhzHcXKOG3rHcZyc44becRwn59Tro5e0CXADsBHwLXC1mY2WtD5wG9ARmAf82Mw+VkhVGw3sBXwBjDCzGU0j33GcTHDOOst9aIOVer9PV1qKsywNmdEvAX5lZl2AfsCJkrYGTgceMbPNgUfiNsCewObxbyRwZaOrdhzHaSTWXnttAObNm8e2227bZPs566yzmDhxYpO9f13UO6M3s/eA9+L9RZLmAhsD+wG7xKeNAx4DTovjN1jIxHpK0rqS2sf3cRzH+c6xdOlSRo0alWz/K+Sjl9QR2A54GtiwYLzjbeEKbWPg7aKXzY9jNd9rpKTpkqYvWLBgxZU7jvOdZt68eXTp0oVjjz2WbbbZhkGDBvHll1/y6quvsttuu9G9e3d69uzJa6+9xueff87AgQPp2bMnXbt2rSx1sDxmz55Nnz596NGjB926deOVV15ZroatttqK4cOH061bNw466CC++OILADp27MioUaMYMGAAd9xxByNGjKisWNmxY0fOPPNM+vfvT69evZgxYwaDBw+mc+fOjVpuoUCDDb2ktYG7gF+a2Wd1PbWWsWXqLJjZ1WbWy8x6tWvXrqEyHMdxKnnllVc48cQTmT17Nuuuuy533XUXhx12GCeeeCLPP/88U6ZMoX379rRs2ZJ77rmHGTNm8Oijj/KrX/2Kusq/jBkzhpNOOomKigqmT59Ohw4dlvvcl156iZEjRzJz5kxat27NFVdcUflYy5YtmTx5MgcffPAyr9tkk02YOnUqO+64Y+VJ4KmnnuKss85atQ+lFhpk6CW1IBj5m83s7jj8vqT28fH2wAdxfD6wSdHLOwDvNo5cx3GcKjp16lRZVXL77bfnjTfe4J133mH//fcHgqFdc801MTPOPPNMunXrxm677cY777xTZ/ep/v3788c//pE//elPvPnmm3WWK95kk03YYYcdADj88MOZPHly5WPDhg1b7uuGDBkCQNeuXenbty+tWrWiXbt2tGzZkk8++aThH0IDqNfQxyiaa4G5ZnZx0UPjgeHx/nDgvqLxnyjQD/jU/fOO4zQFhXrvEGq+f/zxx7U+7+abb2bBggU8++yzVFRUsOGGG/LVV18t930PPfRQxo8fzxprrMHgwYOZNGnScp9bsyZ+8XZdpYcL2ps1a1bt/2jWrFmjV7NsSAmEHYAjgFmSChX6zwQuAG6XdDTwFlBo0/IAIbTyVUJ4ZXnmDDuO03DqCIcsZfXK1q1b06FDB+69915+9KMfsXjxYpYuXcqnn37KBhtsQIsWLXj00Ud5880363yf119/nc0224xf/OIXvP7668ycOZNdd629kutbb73F1KlT6d+/P7feeisDBgxoin9tlWhI1M1kave7Awys5fkGnLiKuhzHcVaKG2+8keOOO46zzjqLFi1acMcdd3DYYYex77770qtXL3r06MFWW21V53vcdttt3HTTTbRo0YKNNtqoTr95ly5dGDduHMcddxybb745P/3pTxv7X1plvB69Uw3/rJyG4PXoA/PmzWOfffbhhRdeaPJ9eT16x3EcZ7l4mWLHcZx6WLhwIQMHLuOp5pFHHinJbH5VcUPvOI5TD23atKGioqL+J2YUd904juPkHDf0juM4OccNveM4Ts5xH73jOKtM13FdG/X9Zg2f1ajvVxdrr702n3/+eUlDJUuNz+gdx3EaATPj22+/TS2jVtzQO45TlmSlTHGXLl044YQT6NmzJ2+//TYTJkygf//+9OzZk6FDh/L5558DMG3aNH7wgx/QvXt3+vTpw6JFixr9M1kebugdxylbslKm+Cc/+QnPPfcca621Fueddx4TJ05kxowZ9OrVi4svvpivv/6aYcOGMXr0aJ5//nkmTpxYZ0XMxsZ99I7jlC0NKVMM8M0333DmmWfyxBNP0KxZs8oyxRtttFGt79u/f3/OP/985s+fzwEHHMDmm2++XA2bbrop/fr1A+Cpp55izpw5lWWLv/76a/r3789LL71E+/bt6d27NxCKr5USn9E7jlO2ZKFMcXEpYjNj9913p6KigoqKCubMmcO1116LmS1TzriUuKF3HCc3FJcpBli8eDFffPHFKpUpHjJkCDNnzmzQ/vv168eTTz7Jq6++CsAXX3zByy+/zFZbbcW7777LtGnTAFi0aFGj15yvC3fdOI6zytQVDlnq6pWlLlNcTLt27bj++us55JBDWLx4MQDnnXceW2yxBbfddhs///nP+fLLL1ljjTWYOHEia6+99ir/vw3ByxQ71fDPqryYu1VV2dpJu1xe7bGm/O68THHp8TLFjuM4znJx143jOE491FWmuE2bNgkUrRhu6B3HcerByxQ7juM4mcYNveM4Ts5xQ+84jpNz3EfvOM4qUxzmWRcLG/h+XV6cW+fjn3zyCbfccgsnnHDCcp8zb948pkyZwqGHHgpARUUF7777LnvttRcA48ePZ86cOZx++ukNVFW++IzecZyy45NPPuGKK66o8znz5s3jlltuqdyuqKjggQceqNweMmTId8LIg8/oHccpQ04//XRee+01evTowe677w7Agw8+iCR+97vfMWzYME4//XTmzp1Ljx49OOSQQ7j88sv58ssvmTx5MmeccQZffvkl06dP57LLLmPEiBGsscYavPjii7z55puMHTuWcePGMXXqVPr27cv1118PwIQJEzj77LNZvHgxnTt3ZuzYsSXLbl0VfEbvOE7ZccEFF9C5c2cqKiro168fFRUVleV/Tz31VN577z0uuOACdtxxRyoqKjjttNMYNWoUw4YNo6KigmHDhi3znh9//DGTJk3ir3/9K/vuuy8nn3wys2fPZtasWVRUVPDhhx/WWoK4HPAZveM4Zc3kyZM55JBDaN68ORtuuCE777wz06ZNW+FSwPvuuy+S6Nq1KxtuuCFd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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"profile_df.plot.bar(x=\"callee_func\")"
]
}
],
"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.7"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment