Skip to content

Instantly share code, notes, and snippets.

@Wheest
Created June 3, 2019 11:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Wheest/ab8513066b21ad83df55d010da0b2e7e to your computer and use it in GitHub Desktop.
Save Wheest/ab8513066b21ad83df55d010da0b2e7e 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": [
"%reload_ext autoreload\n",
"%autoreload 2\n",
"\n",
"import numpy as np\n",
"\n",
"from tvm import relay\n",
"from tvm.relay import testing\n",
"from tvm.relay.testing import layers\n",
"from tvm.relay.op.nn import nn\n",
"\n",
"from tvm.relay.testing.init import create_workload\n",
"import tvm\n",
"from tvm.contrib import graph_runtime\n",
"import matplotlib.pyplot as plt\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def ideal_grouped_speed_up(t_1, max_groups):\n",
" \"\"\"The inference time for a grouped convolution is `t_1/num_groups`\n",
" in theory, where `t_1` is the inference time for a standard convolutional\n",
" layer (num_groups==1)\n",
" \n",
" This function generates the ideal time for our experiments\n",
" \"\"\"\n",
" x = np.linspace(1,max_groups,1000)\n",
" y = t_1/x\n",
" return x,y"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"26 26\n"
]
}
],
"source": [
"# set hyperparams\n",
"batch_size = 1\n",
"in_c = 512\n",
"num_filters = 512\n",
"in_h, in_w = 28, 28\n",
"kdim = 3\n",
"groups=1\n",
"stride=1\n",
"pad=0\n",
"data_shape = (batch_size, in_c, in_h, in_w)\n",
"num_groups = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]\n",
"out_h = (in_h + 2* pad - kdim) // stride + 1\n",
"out_w = (in_w + 2* pad - kdim) // stride + 1\n",
"print(out_w, out_h)\n",
"out_shape = (1, num_filters, out_h, out_w)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def conv_block(data, name, num_filters, kernel_size=(3, 3), strides=(1, 1),\n",
" padding=(1, 1), groups=1, dtype='float32'):\n",
" \"\"\"Helper function to construct conv layer\"\"\"\n",
" kdim1, kdim2 = kernel_size\n",
" weight = relay.var(name + \"_weight\")\n",
" conv = nn.conv2d(\n",
" data=data,\n",
" weight=weight,\n",
" channels=num_filters,\n",
" kernel_size=kernel_size,\n",
" strides=strides,\n",
" padding=padding,\n",
" groups=groups)\n",
" return conv"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def weenet(data_shape, num_filters, kdim, stride,\n",
" pad, groups, dtype='float32'):\n",
" \"\"\"Function to construct a WeeNet\"\"\"\n",
" data = relay.var(\"data\", shape=data_shape, dtype=dtype)\n",
" body = conv_block(data, 'conv_block_1', num_filters, (kdim,kdim), \n",
" (stride,stride), (pad,pad), groups, dtype)\n",
" return relay.Function(relay.ir_pass.free_vars(body), body)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def get_workload(data_shape, num_filters, kdim, stride,\n",
" pad, groups, dtype='float32'):\n",
" net = weenet(data_shape, num_filters, kdim, stride, pad, groups, dtype)\n",
" return create_workload(net)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def compile_model(net, params, data, opt_level=1, ctx=tvm.cpu(0), target='llvm'):\n",
" with relay.build_config(opt_level=opt_level):\n",
" graph, lib, params = relay.build_module.build(\n",
" net, target, params=params)\n",
" # create module\n",
" module = graph_runtime.create(graph, lib, ctx)\n",
" # set input and parameters\n",
" module.set_input(\"data\", data)\n",
" module.set_input(**params)\n",
" # run\n",
" module.run()\n",
" # get output\n",
" out = module.get_output(0, tvm.nd.empty(out_shape)).asnumpy()\n",
" return out, module"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# create random input\n",
"np.random.seed(0)\n",
"data_shape = (batch_size, in_c, in_h, in_w)\n",
"data = np.random.uniform(-1, 1, size=data_shape).astype(\"float32\")\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Cannot find config for target=llvm, workload=('conv2d', (1, 512, 28, 28, 'float32'), (512, 512, 3, 3, 'float32'), (1, 1), (0, 0), (1, 1), 'NCHW', 'float32'). A fallback configuration is used, which may bring great performance regression.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"222.53500015\n",
"861.6288232\n",
"406.10519155\n",
"197.30839095\n",
"92.9214976\n",
"44.026740600000004\n",
"19.5444554\n",
"3.2048008999999995\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING:autotvm:Cannot find config for target=llvm, workload=('depthwise_conv2d_nchw', (1, 512, 28, 28, 'float32'), (512, 1, 3, 3, 'float32'), (1, 1), (0, 0), (1, 1), 'float32'). A fallback configuration is used, which may bring great performance regression.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"1.4647264500000001\n",
"0.9434844499999999\n"
]
}
],
"source": [
"results = [None] * len(num_groups)\n",
"ctx=tvm.cpu(0)\n",
"target = 'llvm'\n",
"opt_level = 1\n",
"\n",
"for i, g in enumerate(num_groups):\n",
" net, params = get_workload(data_shape, num_filters, kdim, stride, pad, g)\n",
" out, m = compile_model(net, params, data, opt_level, ctx, target)\n",
" f = m.module.time_evaluator('run', ctx, repeat=10)\n",
" results[i] = np.median(f().results) * 1000\n",
" print(results[i])"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[222.53500015,\n",
" 861.6288232,\n",
" 406.10519155,\n",
" 197.30839095,\n",
" 92.9214976,\n",
" 44.026740600000004,\n",
" 19.5444554,\n",
" 3.2048008999999995,\n",
" 1.4647264500000001,\n",
" 0.9434844499999999]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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+vXrxxVXXEG3bt3o1KkTc+fOBUgaZ6ydkSNHcsQRR9ClSxfuueceIMyGedlll9GuXTsGDhzIl19+WbLv+B7IefPm0a9fPwDGjBnD2WefTZ8+fTjssMO47777qvam1RCa3CXNYhO4aFZPERERkTrgN7+BBQvS22a3bnDbbZXadNmyZTz++OPcd999nHbaaTzzzDOcddZZXHjhhdx9990cdthhzJkzh1//+tfMmDGDESNGcM4553DOOefwwAMPcPnllzN16lQgPLZi9uzZZGVlcd1119G/f38eeOABCgsLOfLIIxk4cCB/+MMfmDdvHn/7298AmDBhQkksl19+OT/+8Y+ZMmUKW7duZf369QA88MAD7L333hQVFXHEEUdw6qmnss8++yQ9ngULFpCfn8+HH34IQGFhYcm67777jgULFjBr1izOPfdcPvzwQ/74xz8mjXPixIk0a9aMt99+m02bNtG3b1+OP/545s+fz5IlS1i4cCGrV6+mQ4cOnHvuueWe5/fff5+33nqLDRs20L17d0488URatmxZqfesplDilwFDu7dSoiciIiIiade2bVu6desGQM+ePVmxYgXr169n9uzZDBs2rKTepk2bAHjzzTeZPHkyAGeffTbXXHNNSZ1hw4aRlRVGqr388stMmzaNW265BQiPtIj1DpZmxowZPPzwwwBkZWXRrFkzAO644w6mTJkCwOeff86yZctKTfwOOeQQPvnkE0aMGMGJJ57I8ccfX7LujDPOAOCYY47hm2++obCwsNQ4X375Zd5///2S+/fWrVvHsmXLmDVrFmeccQZZWVm0bNmS/v37l32CI0OGDCEnJ4ecnByOPfZY5s6dy9ChQ1PatqZS4iciIiIiUppK9sxlSoMGDUp+z8rKoqioiG3bttG8eXMWVLBnsnHjxiW/uzvPPPMM7drteHvSnDlzKtTmzJkzefXVV3nzzTdp1KgR/fr1Y+PGjaXW32uvvXjvvfeYPn06d999N08++SQPPPAAsPPjC8ys1DjdnTvvvJPc3NwdyuPvT0xUv359tm3bBrBTjMn2XdvpHj8RERERkVpszz33pG3btjz11FNASILee+89AH74wx/yxBNPADBx4kSOPvropG3k5uZy55134u4AzJ8/H4CmTZvy7bffJt1mwIAB3HXXXUC4x27dunWsW7eOvfbai0aNGrF48WLeeuutMmNfs2YN27Zt49RTT+Xmm2/m3XffLVk3adIkAF5//XWaNWtGs2bNSo0zNzeXu+66i+LiYgCWLl3Khg0bOOaYY5g0aRJbt25l1apVvPbaayXtt2nThnfeeQeAZ555Zoe4nn32WTZu3MjatWuZOXMmRxxxRJnHURso8RMRERERqeUmTpzI+PHj6dq1Kx07diyZ9OTOO+/kwQcfpEuXLjzyyCPcfvvtSbe//vrrKS4upkuXLnTs2JHrr78egGOPPZaFCxeWTO4S7/bbb+e1116jc+fO9OzZk4ULFzJo0CC2bNlC+/btGTVqFL179y4z7vyqTsG3AAAgAElEQVT8fPr160e3bt0466yz+POf/1yyrmHDhnTv3p2LL76Y8ePHlxnn+eefT4cOHejRowedOnXioosuYsuWLZx88skcdthhdOjQgV/+8pf06dOnpP3Ro0dzxRVX0KtXr5IhrzFdunTh2GOPpXfv3lx//fW1/v4+AItly7VRr169fN68edUdhoiIiIjUIYsWLaJ9+/bVHcZurV+/ftxyyy306tVrl+97zJgxNGnShKuvvnqX77s8ya5NM3vH3cs9UerxExERERERqeM0uYuIiIiIiNQoM2fOrLZ9jxkzptr2nUkZ7fEzsyvN7CMz+9DMHjezhmbW1szmmNlyM5tkZntEdRtEy8uj9W0yGZuIiIiIiMjuImOJn5m1Ai4Herl7JyAL+Dnwv8Ct7v594GvgvGiT84Cvo/Jbo3oiIiIiIiJSRZm+x68+kGNm9YFGwCqgP/B0tP4hIPYkxCHRMtH6AVYXHpghIiIiIiJSzTKW+Ll7PnAL8Bkh4VsHvAMUuvuWqFoe0Cr6vRXwebTtlqj+PontmtmFZjbPzOYVFBRkKnwREREREZE6I5NDPfci9OK1BVoCjYFBVW3X3e91917u3mu//faranMiIiIiIjVOVlYW3bp1K3mNHTs2o/ubNm1axvcxc+ZMZs+eXW69CRMmcNlll5Vbr02bNqxZs6bMOn/6059Sji/ez372Mz755JNKbVtVV199NTNmzEh7u5mc1XMg8F93LwAws8lAX6C5mdWPevVaA/lR/XzgICAvGhraDFibwfhERERERGqknJwcFixYsEv2tWXLFgYPHszgwYMzup+ZM2fSpEkTfvjDH2Z0P/H+9Kc/cd1111Vom48++oitW7dyyCGHZCiqso0YMYILLriA/v37p7XdTN7j9xnQ28waRffqDQAWAq8BP4vqnAM8G/0+LVomWj/Da/PT5UVERERktzB1fj59x86g7agX6Dt2BlPn55e/USWsW7eOdu3asWTJEgDOOOMM7rvvPgCaNGnClVdeSceOHRkwYACxW6I+/vhjBg0aRM+ePTn66KNZvHgxAMOHD+fiiy/mqKOO4pprrtmhl2348OFccskl9O7dm0MOOYSZM2dy7rnn0r59e4YPH14Sz8svv0yfPn3o0aMHw4YNY/369UDoiRs9ejQ9evSgc+fOLF68mBUrVnD33Xdz66230q1bN/7zn//w3HPPcdRRR9G9e3cGDhzI6tWryzz+tWvXcvzxx9OxY0fOP/984lOFoUOH0rNnTzp27Mi9994LwKhRoygqKqJbt26ceeaZpdZLNHHiRIYMGVKy3KRJE0aOHEnHjh0ZOHAgc+fOpV+/fhxyyCFMmzYNgK1btzJy5EiOOOIIunTpwj333APA+vXrGTBgQMm5ePbZkPqsWLGC9u3bc8EFF9CxY0eOP/54ioqKADj44INZu3YtX3zxRZnno8LcPWMv4EZgMfAh8AjQADgEmAssB54CGkR1G0bLy6P1h5TXfs+ePV1EREREJJ0WLlyYct0p7+b54b9/yQ/+3fMlr8N//5JPeTevSjHUq1fPu3btWvJ64okn3N395Zdf9t69e/vjjz/uubm5JfUBf/TRR93d/cYbb/RLL73U3d379+/vS5cudXf3t956y4899lh3dz/nnHP8xBNP9C1btri7+4MPPliyzTnnnOOnn366b9u2zadOnepNmzb1999/37du3eo9evTw+fPne0FBgR999NG+fv16d3cfO3as33jjje7ufvDBB/sdd9zh7u5///vf/bzzznN399GjR/u4ceNKYv7qq69827Zt7u5+3333+VVXXbVTLPFGjBhRso/nn3/eAS8oKHB397Vr17q7+3fffecdO3b0NWvWuLt748aNd2ijtHrxjjnmGH///fd3OLcvvviiu7sPHTrUjzvuON+8ebMvWLDAu3bt6u7u99xzj990003u7r5x40bv2bOnf/LJJ15cXOzr1q1zd/eCggI/9NBDfdu2bf7f//7Xs7KyfP78+e7uPmzYMH/kkUdK9nn++ef7008/vVNsya5NYJ6nkJtl9AHu7j4aGJ1Q/AlwZJK6G4FhmYxHRERERCSdxk1fQlHx1h3Kioq3Mm76EoZ2b1XKVuUrbajncccdx1NPPcWll17Ke++9V1Jer149Tj/9dADOOussTjnlFNavX8/s2bMZNmz7V+xNmzaV/D5s2DCysrKS7v+kk07CzOjcuTP7778/nTt3BqBjx46sWLGCvLw8Fi5cSN++fQHYvHkzffr0Kdn+lFNOAaBnz55Mnjw56T7y8vI4/fTTWbVqFZs3b6Zt27ZlnpNZs2aVtHXiiSey1157lay74447mDJlCgCff/45y5YtY599dponMqV6q1atIn4ukT322INBg8JUJZ07d6ZBgwZkZ2fTuXNnVqxYAYTez/fff5+nnw4PL1i3bh3Lli2jdevWXHfddcyaNYt69eqRn59f0rPZtm1bunXrVnKeYm0BtGjRgpUrV5Z5Pioqo4mfiIiIiEhdtrKwqELlVbVt2zYWLVpEo0aN+Prrr2ndunXSembGtm3baN68ean3CjZu3LjU/TRo0AAICWXs99jyli1byMrK4rjjjuPxxx8vc/usrCy2bNmStM6IESO46qqrGDx4MDNnzmTMmDGlxlOWmTNn8uqrr/Lmm2/SqFEj+vXrx8aNGytdLycnZ4fy7OxsYk+Ziz8fsXMBYRTlnXfeSW5u7g5tTZgwgYKCAt555x2ys7Np06ZNSdvx5zUrK6tkqCfAxo0bycnJqdT5KE2mn+MnIiIiIlJntWye/Mt5aeVVdeutt9K+fXsee+wxfvWrX1FcXAyEhDDW2/TYY4/xox/9iD333JO2bdvy1FNPASE5ie8lrIrevXvzxhtvsHz5cgA2bNjA0qVLy9ymadOmfPvttyXL69ato1Wr0Cv60EMPlbZZiWOOOYbHHnsMgJdeeomvv/66pJ299tqLRo0asXjxYt56662SbbKzs0vOUVn14rVv377kuFKVm5vLXXfdVbKvpUuXsmHDBtatW0eLFi3Izs7mtdde49NPP02pvaVLl9KpU6cKxVAeJX4iIiIiIpU0MrcdOdk7DpfMyc5iZG67KrUbm5Qk9ho1ahRLlizh/vvv5y9/+QtHH300xxxzDDfffDMQeu/mzp1Lp06dmDFjBjfccAMQJioZP348Xbt2pWPHjiWTi1TVfvvtx4QJEzjjjDPo0qULffr0KZk4pjQnnXQSU6ZMKZncZcyYMQwbNoyePXuy7777lrvP0aNHM2vWLDp27MjkyZP53ve+B8CgQYPYsmUL7du3Z9SoUfTu3btkmwsvvJAuXbpw5plnllkv3oknnsjMmTNTPxnA+eefT4cOHejRowedOnXioosuYsuWLZx55pnMmzePzp078/DDD3P44YeX21ZxcTHLly+nV69eFYqhPOa1eOLMXr16+bx586o7DBERERGpQxYtWkT79u1Trj91fj7jpi9hZWERLZvnMDK3XZXu76uMJk2alMyqKVVTVFTEscceyxtvvFHqPZCZNGXKFN59911uuummndYluzbN7B13LzdL1D1+IiIiIiJVMLR7q12e6Enm5OTkcOONN5Kfn1/Sq7grbdmyhd/+9rdpb1eJn4iIiIhILafevvRKnKRlV4qfhTWddI+fiIiIiEiC2nw7lNRNVb0mlfiJiIiIiMRp2LAha9euVfInNYa7s3btWho2bFjpNjTUU0REREQkTuvWrcnLy6OgoKC6QxEp0bBhw1Kf25gKJX4iIiIiInGys7Np27ZtdYchklYa6ikiIiIiIlLHKfETERERERGp45T4iYiIiIiI1HFK/EREREREROo4JX4iIiIiIiJ1nBI/ERERERGROk6Jn4iIiIiISB2nxE9ERERERKSOU+InIiIiIiJSxynxExERERERqeOU+ImIiIiIiNRxSvxERERERETqOCV+IiIiIiIidZwSPxERERERkTpOiZ+IiIiIiEgdp8RPRERERESkjlPiJyIiIiIiUscp8RMREREREanjlPiJiIiIiIjUcUr8RERERERE6jglfiIiIiIiInWcEj8REREREZE6rn55FcysNfBz4GigJVAEfAi8ALzk7tsyGqGIiIiIiIhUSZmJn5k9CLQCngf+F/gSaAj8ABgE/I+ZjXL3WZkOVERERERERCqnvB6/v7j7h0nKPwQmm9kewPfSH5aIiIiIiIikS5n3+CVL+sxsLzPrEq3f7O7LMxWciIiIiIiIVF1Kk7uY2Uwz29PM9gbeBe4zs1szG5qIiIiIiIikQ6qzejZz92+AU4CH3f0oYEB5G5lZczN72swWm9kiM+tjZnub2Stmtiz6uVdU18zsDjNbbmbvm1mPyh+WiIiIiIiIxKSa+NU3swOB0wgTvaTqduCf7n440BVYBIwC/uXuhwH/ipYBTgAOi14XAndVYD8iIiIiIiJSilQTvz8A04Hl7v62mR0CLCtrAzNrBhwDjIeS+wELgSHAQ1G1h4Ch0e9DCL2J7u5vAc2jZFNERERERESqIKXEz92fcvcu7v7raPkTdz+1nM3aAgXAg2Y238zuN7PGwP7uviqq8wWwf/R7K+DzuO3zorIdmNmFZjbPzOYVFBSkEr6IiIiIiMhurdwHuAOYWVtgBNAmfht3H1xO2z2AEe4+x8xuZ/uwztj2bmZekYDd/V7gXoBevXpVaFsREREREZHdUUqJHzCVMGTzOWBbitvkAXnuPidafpqQ+K02swPdfVU0lPPLaH0+cFDc9q2jMhEREREREamCVBO/je5+R0UadvcvzOxzM2vn7ksIs4AujF7nAGOjn89Gm0wDLjOzJ4CjgHVxQ0JFRERERESkklJN/G43s9HAy8CmWKG7v1vOdiOAiWa2B/AJ8CvCfYVPmtl5wKeEmUIBXgR+AiwHvovqioiIiIiISBWlmvh1Bs4G+rN9qKdHy6Vy9wVArySrdnoGoLs7cGmK8YiIiIiIiEiKUk38hgGHuPvmTAYjIiIiIiIi6Zfqc/w+BJpnMhARERERERHJjFR7/JoDi83sbXa8x6+sxzmIiIiIiIhIDZBq4jc6o1GIiIiIiIhIxpSZ+JmZefDv8uqkPzQRERERERFJh/Lu8XvNzEaY2ffiC81sDzPrb2YPEZ7FJyIiIiIiIjVUeUM9BwHnAo+bWVugEMghJIwvA7e5+/zMhigiIiIiIiJVUWbi5+4bgX8A/zCzbGBfoMjdC3dFcCIiIiIiIlJ1qU7ugrsXA6syGIuIiIiIiIhkQKrP8RMREREREZFaSomfiIiIiIhIHZdy4mdmB5vZwOj3HDNrmrmwREREREREJF1SSvzM7ALgaeCeqKg1MDVTQYmIiIiIiEj6pNrjdynQF/gGwN2XAS0yFZSIiIiIiIikT6qJ3yZ33xxbMLP6gGcmJBEREREREUmnVBO/f5vZdUCOmR0HPAU8l7mwREREREREJF1STfxGAQXAB8BFwIvA7zMVlIiIiIiIiKRPSg9wd/dtwH3RS0RERERERGqRVGf1/KmZzTezr8zsGzP71sy+yXRwIiIiIiIiUnUp9fgBtwGnAB+4uyZ1ERERERERqUVSvcfvc+BDJX0iIiIiIiK1T6o9ftcAL5rZv4FNsUJ3/2tGohIREREREZG0STXx+yOwHmgI7JG5cERERERERCTdUk38Wrp7p4xGIiIiIiIiIhmR6j1+L5rZ8RmNRERERERERDIi1cTvEuCfZlakxzmIiIiIiIjULqk+wL1ppgMRERERERGRzCgz8TOzw919sZn1SLbe3d/NTFgiIiIiIiKSLuX1+F0FXAj8Jck6B/qnPSIRERERERFJqzITP3e/MPr1BHffGL/OzBpmLCoRERERERFJm1Qnd5mdYpmIiIiIiIjUMOXd43cA0ArIMbPugEWr9gQaZTg2ERERERERSYPy7vHLBYYDrQn3+cUSv2+A6zIXloiIiIiIiKRLeff4PQQ8ZGanuvszuygmERERERERSaOU7vFT0iciIiIiIlJ7pTq5i4iIiIiIiNRS5d3jJ1U0dX4+46YvYWVhES2b5zAytx1Du7eq7rBERERERGQ3klKPn5k1MrPrzey+aPkwM/tpittmmdl8M3s+Wm5rZnPMbLmZTTKzPaLyBtHy8mh9m8odUs0xdX4+107+gPzCIhzILyzi2skfMHV+fnWHJiIiIiIiu5FUh3o+CGwC+kTL+cDNKW57BbAobvl/gVvd/fvA18B5Ufl5wNdR+a1RvVpt3PQlFBVv3aGsqHgr46YvqaaIRERERERkd5Rq4neou/8fUAzg7t+x/dEOpTKz1sCJwP3RsgH9gaejKg8BQ6Pfh0TLROsHRPVrrZWFRRUqFxERERERyYRUE7/NZpYDOICZHUroASzPbcA1wLZoeR+g0N23RMt5hAfEE/38HCBavy6qvwMzu9DM5pnZvIKCghTDrx4tm+dUqFxERERERCQTUk38RgP/BA4ys4nAvwgJXamiewC/dPd3qhbijtz9Xnfv5e699ttvv3Q2nXYjc9uRk521Q1lOdhYjc9tVU0QiIiIiIrI7SmlWT3d/xczeBXoThnhe4e5rytmsLzDYzH4CNAT2BG4HmptZ/ahXrzXhfkGinwcBeWZWH2gGrK3oAdUksdk7NauniIiIiIhUp5QSPzM7GZjh7i9Ey83NbKi7Ty1tG3e/Frg2qt8PuNrdzzSzp4CfAU8A5wDPRptMi5bfjNbPcHev1FHVIEO7t1KiJyIiIiIi1SrloZ7uvi624O6FhOGflfE74CozW064h298VD4e2CcqvwoYVcn2RUREREREJE6qD3BPliCm/PB3d58JzIx+/wQ4MkmdjcCwVNsUERERERGR1KTa4zfPzP5qZodGr78CaZ20RURERERERDIj1cRvBLAZmBS9NgGXZiooERERERERSZ9UZ/XcgO65ExERERERqZVSndXzB8DVQJv4bdy9f2bCEhERERERkXRJdYKWp4C7gfuBrZkLR0RERERERNIt1cRvi7vfldFIREREREREJCNSndzlOTP7tZkdaGZ7x14ZjUxERERERETSItUev3OinyPjyhw4JL3hiIiIiIiISLqlOqtn20wHIiIiIiIiIpmR0lBPM2tkZr83s3uj5cPM7KeZDU1ERERERETSIdV7/B4kPMD9h9FyPnBzRiISERERERGRtEo18TvU3f8PKAZw9+8Ay1hUIiIiIiIikjapJn6bzSyHMKELZnYosCljUYmIiIiIiEjapDqr52jgn8BBZjYR6AsMz1RQIiIiIiIikj7lJn5mZsBi4BSgN2GI5xXuvibDsYmIiIiIiEgalJv4ubub2Yvu3hl4YRfEJCIiIiIiImmU6j1+75rZERmNRERERERERDIi1Xv8jgLONLNPgQ2E4Z7u7l0yFpmIiIiIiIikRaqJX25GoxAREREREZGMSWmop7t/ChwE9I9+/y7VbUVERERERKR6pZS8mdlo4HfAtVFRNvBopoISERERERGR9Em11+5kYDDh/j7cfSXQNFNBiYiIiIiISPqkmvhtdncHHMDMGmcuJBEREREREUmnVBO/J83sHqC5mV0AvArcl7mwREREREREJF3KnNXTzBq4+yZ3v8XMjgO+AdoBN7j7K7skQhEREREREamS8h7n8CbQw8wecfezASV7IiIiIiIitUx5id8eZvYL4IdmdkriSnefnJmwREREREREJF3KS/wuBs4EmgMnJaxzQImfiIiIiIhIDVdm4ufurwOvm9k8dx+/i2ISERERERGRNCqvxw8Adx9vZj8E2sRv4+4PZyguERERERERSZOUEj8zewQ4FFgAbI2KHVDiJyIiIiIiUsOllPgBvYAO0UPcRUREREREpBZJNfH7EDgAWJXBWGq9qfPzGTd9CSsLi2jZPIeRue0Y2r1VdYclIiIiIiK7uVQTv32BhWY2F9gUK3T3wRmJqhaaOj+fayd/QFFxGAmbX1jEtZM/AFDyJyIiIiIi1SrVxG9MJoOoC8ZNX0JR8VaumvUIXb5YzvDTbqSoeCvjpi9R4iciIiIiItUq1Vk9/53pQGq7lYVFAOz7XSEdvvxkp3IREREREZHqUq+slWb2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\n",
"text/plain": [
"<Figure size 1080x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"fig, axs = plt.subplots(1, 1, figsize=(15, 4), sharey=True)\n",
"fig.suptitle('Groups Variation of Grouped Convolution blocks (tvm+llvm)', fontsize=15)\n",
"opt_level = 0\n",
"i = opt_level - 1\n",
"col_header = 'opt_level_' + str(opt_level)\n",
"x,y = ideal_grouped_speed_up(results[0], num_groups[-1])\n",
"axs.scatter(x=num_groups, y=results, \n",
" label='Experimental data (mean)')\n",
"axs.plot(x,y,c='r',label='Theoretical speedup')\n",
"axs.legend()\n",
"axs.set_title('optimisation level '+str(opt_level))\n",
"axs.set_xlabel('groups')\n",
"axs.set_ylabel('inference time (ms)')\n",
"\n",
"fig.savefig(\"/tmp/tvm_group_variation.png\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "meth",
"language": "python",
"name": "meth"
},
"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.5.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment