Created
August 7, 2017 13:25
-
-
Save fbcotter/2b7066c861ec93075c1cead42e23b2e7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Speed Comparisons between the Numpy an TF implementations of the DTCWT\n", | |
| "Operations were performed on a system with a GTX 1080 GPU and Intel Xeon CPU E5-2660 CPU" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:30:49.826397Z", | |
| "start_time": "2017-08-07T11:30:48.221518Z" | |
| } | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "%matplotlib inline\n", | |
| "import matplotlib.pyplot as plt\n", | |
| "import datasets\n", | |
| "import dtcwt\n", | |
| "import dtcwt.tf\n", | |
| "import tensorflow as tf\n", | |
| "from time import time\n", | |
| "import numpy as np\n", | |
| "import os\n", | |
| "import py3nvml\n", | |
| "plt.style.use('seaborn')\n", | |
| "py3nvml.grab_gpus(1);" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Analysis of Small Images" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "collapsed": true | |
| }, | |
| "source": [ | |
| "## DTCWT on a single small image (64x64)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:30:51.360177Z", | |
| "start_time": "2017-08-07T11:30:49.828104Z" | |
| }, | |
| "collapsed": true | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "# Create the input\n", | |
| "h, w = 64, 64\n", | |
| "in_ = np.random.randn(1,h,w)\n", | |
| "\n", | |
| "# Set up the transforms\n", | |
| "nlevels = 3\n", | |
| "tf.reset_default_graph()\n", | |
| "fwd = dtcwt.Transform2d() # Numpy Transform\n", | |
| "fwd_tf = dtcwt.tf.Transform2d() # Tensorflow Transform\n", | |
| "\n", | |
| "in_placeholder = tf.placeholder(tf.float32, [None, h, w])\n", | |
| "out_tf = fwd_tf.forward(in_placeholder, nlevels=nlevels)\n", | |
| "out_fft = tf.fft2d(tf.cast(in_placeholder, tf.complex64))\n", | |
| "\n", | |
| "sess = tf.Session()\n", | |
| "sess.run(tf.global_variables_initializer())" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Numpy Implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:30:56.101356Z", | |
| "start_time": "2017-08-07T11:30:51.362870Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "5.63 ms ± 592 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "small_np = %timeit -o for i in in_: fwd.forward(i, nlevels=nlevels)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### TF implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:30:56.989200Z", | |
| "start_time": "2017-08-07T11:30:56.103634Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "2.26 ms ± 444 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "small_tf = %timeit -o sess.run(out_tf.lowpass_op, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### (Comparison) Using an FFT in Tensorflow\n", | |
| "We can safely assume that something like the FFT is an optimized, fast operation to do. This is a good yardstick to gauge the overheads with working on a GPU" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:30:57.470088Z", | |
| "start_time": "2017-08-07T11:30:56.992097Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "3.82 ms ± 68.2 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit sess.run(out_fft, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## DTCWT on a batch of small images (100x64x64)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:30:57.510947Z", | |
| "start_time": "2017-08-07T11:30:57.473103Z" | |
| }, | |
| "collapsed": true | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "in_ = np.random.randn(100,h,w)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Numpy Implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 7, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:31:02.709545Z", | |
| "start_time": "2017-08-07T11:30:57.513113Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "642 ms ± 68.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "small_np_batch = %timeit -o for i in in_: fwd.forward(i, nlevels=nlevels)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### TF implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 8, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:31:04.972253Z", | |
| "start_time": "2017-08-07T11:31:02.713718Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "2.77 ms ± 126 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "small_tf_batch = %timeit -o sess.run(out_tf.lowpass_op, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### (Comparison) Using an FFT in Tensorflow" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 9, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:31:10.279027Z", | |
| "start_time": "2017-08-07T11:31:04.975413Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "6.53 ms ± 439 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit sess.run(out_fft, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Small Image Conclusion" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 10, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:31:10.504659Z", | |
| "start_time": "2017-08-07T11:31:10.282293Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "image/png": "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\nSRo8eLASExOVnZ2tvn37qnfv3po+fbrOnTune++9Vw0bNtSrr76quLg4vfXWW7LZbGrUqJFe+e9v\nZdm9e7feeecdnTx5UiNHjlTXrl2L9b4pqa5kv5KkAwcOqHfv3kpNTdUTTzyhBx98UJmZmRo8eLDS\n09OVl5enf/7zn+rUqdMF6x49erRiY2O1cuVK2Ww2dejQQSNGjJAkff7555o0aZIyMjI0depUBQUF\nuePucA0LLnP06FHr1ltvtb777jvLsixr6NChVlxcnGVZlvXoo49a48ePtyzLsnbu3Gl17979gstH\nR0dbK1assCzLsrKzs62zZ89almVZLVq0sCzLsrZv3261atXKOnHihJWfn289+OCD1q5du6xz585Z\nHTp0sI4cOWJZlmU988wz1oABAyzLsqylS5dakyZNsizLsoYPH27t2rXLsizLOnbsmNW1a1eX3A+l\nzdGjRy/YHn/c5381cOBAa/fu3ZZlWdaZM2es3NzcApdfunSpFRYWZqWnp1vnzp2z7rzzTuv48eNW\nYmKiddddd1mpqalWTk6O9dBDDzm2y6xZs6x58+ZZlmVZffv2tQ4dOmRZlmUlJCRYUVFRrrjJpc7V\n7ltLly61/va3v1mnTp2yzp49a3Xv3t3at2+fZVmWlZqaalmW5Vh+6tQpy7IKPgZ+/PFHq3PnzlZK\nSkqBy4wePdp6+umnrfz8fOunn36yOnXq5IqbXypdyX41a9YsKyIiwjp79qyVkpJidejQwUpMTLRy\nc3OtjIwMy7IsKyUlxerUqZN1/vz5C9a9adMmq3fv3lZWVpZlWf/bPo8++qg1bdo0x3kee+yxa30z\n3YpX6C5Wu3Zt3XrrrZKkxo0b69ixY47TunfvLkkKDg7WmTNnlJ6eripVqjhOb9GihebMmaPExER1\n7txZdevWvWD9zZo1c/wO/FtuuUXHjh2Tt7e36tSpU+AP3Xz00UcXXHbr1q0F/qLdmTNnlJmZKW/v\n0vDLL0uGVq1a6cUXX1RERIQ6d+580fsuJCREPj6//5riBg0a6NixY0pLS1NwcLCqVasmSeratasO\nHz5c4HKZmZnau3ev/vnPfzqW5eTwx1P+cDX7liS1a9dOvr6+kqTw8HB99dVXatq0qd5//32tXbtW\n0u+v4v/zn/84zveH7du3q2vXrvLz85Mkx3aUpE6dOqlcuXJq2LChfvvtt2t8q8uOjh07qkKFCqpQ\noYLatm2rb775RqGhofrXv/6lXbt2qVy5ckpKSrrofbxt2zbdf//9qlixoqSC2yc8PFzShY8ZExB0\nF/P0/N9fBPLw8FB29v/+hrnNZitw3r/+OyIiQs2bN9emTZs0YMAATZo0SSEhIYWuPz8/3+nZzp8/\nr48++kheXqXldyKXPAMGDFBoaKji4+P10EMPad68eRfcn0XdRpZlqUqVKlqxYsU1ndkUV7NvXeo8\nO3bs0NatW7Vo0SJVrFhRUVFRBdZ7pXOh6C62zVauXKlTp05p2bJlKl++vMLCwoq8fcqVK3dFPy9L\nAz4U50affvqppN/fc/Px8XG8ivvD0aNHVadOHfXt21cdO3bUDz/84NR669Wrp6NHj+rXX38tcD1/\n1b59e73//vuOf3///fdFuRnG8fb2VmZmplPnPXLkiBo1aqQBAwaoadOmOnTokFOXa9q0qXbt2qXT\np08rLy9Pa9asueA8lStXVu3atfXZZ59J+j3wBw4ccP6GlGGX27ckacuWLUpLS9O5c+e0bt06tWrV\nShkZGapataoqVqyoX375RQkJCY7z2+125ebmSpJuv/12ff7550pNTZUkpaWlFcOtKt2uZL+SpPXr\n1ys7O1upqanauXOnmjZtqoyMDFWvXl3ly5fX9u3bHa+w/7rudu3aadmyZTp79qyksrN9eIXuRl5e\nXoqMjFReXp5iYmIuOP2zzz7TihUrZLfbdd1112ngwIFOrbdChQp64YUX9MQTT6hSpUpq0qTJRc83\nfvx4RUdHKyIiQvn5+QoKCuIrbZJ8fX3VqlUr9ejRQ3fccUehn8B99913tWPHDtlsNt10003q0KGD\nkpOTL3sdAQEBGjhwoHr16qWqVauqfv36F43OK6+8ookTJ+rNN99UXl6eunXrpltuueWqbl9ZcLl9\nS/r97aqnn37a8aG4pk2bqlGjRlq4cKHuvvtu1atXTy1atHCc/8EHH9Q999yj2267Ta+++qoGDRqk\nqKgolStXTrfddptefPHF4rp5pdKV7FeS1KhRI/Xt21epqakaPHiwAgICFBERoaeeekoRERFq0qSJ\n6tevf8l1HzhwQD179lT58uUVGhqq4cOHF8fNdCt+9aubREVFadSoUWratKlL1v/He+GWZWnSpEmq\nW7eu+vXr55LrQtH8sY3y8vL0j3/8Qz179nS8v4eic/W+BZRUvEI31OLFi7V8+XLl5ubq1ltvVe/e\nvd09Ev7itdde09atW5Wdna327durU6dO7h4JQCnGK3QAAAzAh+IAADAAQQcAwAAEHQAAAxB0AAAM\nQNABADAAQQcAwAD/DzOv+htPD7E0AAAAAElFTkSuQmCC\n", | |
| "text/plain": [ | |
| "<matplotlib.figure.Figure at 0x7f3e3e9d8d68>" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "objects = ('np single', 'tf single', 'np batch', 'tf batch')\n", | |
| "y_pos = np.arange(len(objects))\n", | |
| "performance = [small_np.average, small_tf.average, small_np_batch.average, small_tf_batch.average]\n", | |
| "performance = [i*1000 for i in performance]\n", | |
| "fig, ax = plt.subplots(1, figsize=(8,8))\n", | |
| "ax.bar(y_pos, performance, align='center', alpha=0.5, color=['red', 'blue'])\n", | |
| "plt.xticks(y_pos, objects)\n", | |
| "plt.ylabel('Time (ms)')\n", | |
| "plt.title('Times to perform DTCWT on small images')\n", | |
| "plt.show()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Analysis of Large Images" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## DTCWT on a single large image (512x512)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 11, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:31:11.373219Z", | |
| "start_time": "2017-08-07T11:31:10.506792Z" | |
| }, | |
| "collapsed": true | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "# Create the input\n", | |
| "h, w = 512, 512\n", | |
| "in_ = np.random.randn(1,h,w)\n", | |
| "\n", | |
| "# Set up the transforms\n", | |
| "nlevels = 3\n", | |
| "tf.reset_default_graph()\n", | |
| "fwd = dtcwt.Transform2d() # Numpy Transform\n", | |
| "fwd_tf = dtcwt.tf.Transform2d() # Tensorflow Transform\n", | |
| "\n", | |
| "in_placeholder = tf.placeholder(tf.float32, [None, h, w])\n", | |
| "out_tf = fwd_tf.forward(in_placeholder, nlevels=nlevels)\n", | |
| "out_fft = tf.fft2d(tf.cast(in_placeholder, tf.complex64))\n", | |
| "\n", | |
| "sess = tf.Session()\n", | |
| "sess.run(tf.global_variables_initializer())" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Numpy Implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 12, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:31:16.031492Z", | |
| "start_time": "2017-08-07T11:31:11.375442Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "57.3 ms ± 5.27 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "large_np = %timeit -o for i in in_: fwd.forward(i, nlevels=nlevels)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### TF implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 13, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:31:18.058548Z", | |
| "start_time": "2017-08-07T11:31:16.033601Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "2.39 ms ± 109 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "large_tf = %timeit -o sess.run(out_tf.lowpass_op, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### (Comparison) Using an FFT in Tensorflow" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 14, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:31:23.107977Z", | |
| "start_time": "2017-08-07T11:31:18.061652Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "6.19 ms ± 325 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit sess.run(out_fft, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## DTCWT on a batch of large images (100x512x512)\n", | |
| "Batches are something tensorflow naturally handles. This should widen the gap as we only have to copy data to the GPU once for multiple images" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 15, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:31:24.473872Z", | |
| "start_time": "2017-08-07T11:31:23.112698Z" | |
| }, | |
| "collapsed": true | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "in_ = np.random.randn(100,512,512)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Numpy Implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 16, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:32:08.472588Z", | |
| "start_time": "2017-08-07T11:31:24.477445Z" | |
| }, | |
| "scrolled": true | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "5.44 s ± 189 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "large_np_batch = %timeit -o for i in in_: fwd.forward(i, nlevels=nlevels).lowpass" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### TF implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 17, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:32:09.632071Z", | |
| "start_time": "2017-08-07T11:32:08.474983Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "124 ms ± 4.32 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "large_tf_batch = %timeit -o sess.run(out_tf.lowpass_op, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### (Comparison) Using an FFT in Tensorflow" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 18, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:32:10.702518Z", | |
| "start_time": "2017-08-07T11:32:09.634609Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "113 ms ± 2.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit sess.run(out_fft, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## DTCWT on a batch of large images with a convolution afterwards\n", | |
| "This again should widen the gap, as having already calculated something on the GPU, we don't need to transfer the data there again" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 19, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:32:12.112465Z", | |
| "start_time": "2017-08-07T11:32:10.706380Z" | |
| }, | |
| "collapsed": true | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "h, w = 512, 512\n", | |
| "in_ = np.random.randn(100, h, w)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### Numpy Implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 20, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:32:12.156396Z", | |
| "start_time": "2017-08-07T11:32:12.114544Z" | |
| } | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "fwd = dtcwt.Transform2d()\n", | |
| "tf.reset_default_graph()\n", | |
| "sess = tf.Session()\n", | |
| "highs = tf.placeholder(tf.float32, [None, h>>3, w>>3, 6])\n", | |
| "weights = tf.get_variable('weights', shape=(5,5,6,64))\n", | |
| "step = tf.nn.conv2d(highs, weights, strides=[1,1,1,1], padding='SAME')\n", | |
| "sess.run(tf.global_variables_initializer())" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 21, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:32:57.965489Z", | |
| "start_time": "2017-08-07T11:32:12.159253Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "5.7 s ± 139 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "large_np_conv = %timeit -o sess.run(step, {highs: [abs(fwd.forward(i, nlevels=3).highpasses[2]) for i in in_]})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "### TF Implementation" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 22, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:32:58.860531Z", | |
| "start_time": "2017-08-07T11:32:57.968404Z" | |
| }, | |
| "scrolled": false | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "tf.reset_default_graph()\n", | |
| "in_placeholder = tf.placeholder(tf.float32, [None, h, w])\n", | |
| "fwd_tf = dtcwt.tf.Transform2d() \n", | |
| "out_tf = fwd_tf.forward(in_placeholder, nlevels=3)\n", | |
| "p = tf.abs(out_tf.highpasses_ops[2])\n", | |
| "weights = tf.get_variable('weights', shape=(5,5,6,64))\n", | |
| "out = tf.nn.conv2d(p, weights, strides=[1,1,1,1], padding='SAME')\n", | |
| "sess = tf.Session()\n", | |
| "sess.run(tf.global_variables_initializer())" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 23, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T11:33:10.477651Z", | |
| "start_time": "2017-08-07T11:32:58.863436Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "143 ms ± 1.61 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "large_tf_conv = %timeit -o sess.run(out, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Running TF backed on a CPU\n", | |
| "Perhaps there is still a speed-up when using a CPU and tensorflow?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 45, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T12:03:40.293069Z", | |
| "start_time": "2017-08-07T12:03:28.964177Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "12.8 ms ± 389 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# Create the input\n", | |
| "h, w = 512, 512\n", | |
| "in_ = np.random.randn(1,h,w)\n", | |
| "\n", | |
| "# Set up the transforms\n", | |
| "nlevels = 3\n", | |
| "tf.reset_default_graph()\n", | |
| "with tf.device(\"/cpu:0\"):\n", | |
| " fwd_tf = dtcwt.tf.Transform2d() # Tensorflow Transform\n", | |
| " in_placeholder = tf.placeholder(tf.float32, [None, h, w])\n", | |
| " out_tf = fwd_tf.forward(in_placeholder, nlevels=nlevels)\n", | |
| "\n", | |
| "sess = tf.Session()\n", | |
| "sess.run(tf.global_variables_initializer())\n", | |
| "large_tf_cpu = %timeit -o sess.run(out_tf.lowpass_op, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 46, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T12:03:47.646900Z", | |
| "start_time": "2017-08-07T12:03:42.065636Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "516 ms ± 17.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "in_ = np.random.randn(100,h,w)\n", | |
| "large_tf_batch_cpu = %timeit -o sess.run(out_tf.lowpass_op, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 47, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T12:04:18.946481Z", | |
| "start_time": "2017-08-07T12:04:13.202643Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "610 ms ± 27.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "tf.reset_default_graph()\n", | |
| "with tf.device(\"/cpu:0\"):\n", | |
| " in_placeholder = tf.placeholder(tf.float32, [None, h, w])\n", | |
| " fwd_tf = dtcwt.tf.Transform2d() \n", | |
| " out_tf = fwd_tf.forward(in_placeholder, nlevels=3)\n", | |
| " p = tf.abs(out_tf.highpasses_ops[2])\n", | |
| " weights = tf.get_variable('weights', shape=(5,5,6,64))\n", | |
| " out = tf.nn.conv2d(p, weights, strides=[1,1,1,1], padding='SAME')\n", | |
| "sess = tf.Session()\n", | |
| "sess.run(tf.global_variables_initializer())\n", | |
| "large_tf_conv_cpu = %timeit -o sess.run(out, {in_placeholder: in_})" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Large Image Conclusion" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 50, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2017-08-07T12:05:41.444267Z", | |
| "start_time": "2017-08-07T12:05:40.930019Z" | |
| }, | |
| "scrolled": false | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "image/png": "iVBORw0KGgoAAAANSUhEUgAAAtoAAALSCAYAAADjvXZeAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs/X2cV3WB//8/B0ZQkUsXBi9YNy/Xi5RREFCSjyiYIIoB\nq3lVZLmSlWSRtpaaGlurqantGurH7LNpXiRYN+3jdSKVVymr9dH8mrkpODOGCAgKDJ7fH67vnwjS\nqLwG0Pv9L+e83+d9Xu/XnDM+5nDmvOuqqqoCAACsVR3W9QAAAOCDSGgDAEABQhsAAAoQ2gAAUIDQ\nBgCAAoQ2AAAUILThfbjsssty+umnr+thrFeeeeaZHHbYYWlsbMyPf/zjdT2cXHLJJfnqV7+aJJk7\nd24aGxuzYsWKJMlf//rXHH300WlsbMx3vvOdVFWVr3/96xk4cGDGjx+/LofNOnDGGWfkBz/4wboe\nxnty00035ZOf/OS6HkaSDXseYW2rX9cDgPVZY2Nj7b9fffXVdOrUKR07dkySfOtb38qJJ564roZW\nc+yxx+bQQw/NhAkT1vVQkiRXXHFFBg0alJtvvnldD2UVW265ZR599NHa19ddd1169uyZRx55JHV1\ndXn44Yfz61//Ovfee2823XTTdh/f8OHDc+6552afffZZ7eMPPPBAPvWpT2WTTTZJknTt2jWNjY05\n/vjjs/vuu2fu3LkZPXp07flLlizJJptskrq6uiTJ5ZdfngEDBuSxxx7LJZdckkcffTQdOnTI3//9\n3+eTn/xkxo0bl4MOOignn3xyRo0alST53e9+l6OOOioXXnjhSss++9nP5vjjj8+VV16ZJGltbU1r\na2s23njjJG/M9S233FJmotaCm266KTfccEOuvfba2rKzzz57HY7og8M8wv+f0IY1eGuU/a0I+rBr\nbW1NfX39KrH3Xl6jvcydOzfbbbddLUTnzJmTrbba6j1FdnuNvU+fPpk5c2aqqkpzc3Ouu+66HH30\n0Zk2bVqGDBmy0j6700475eabb84222xTW/boo4/mM5/5TCZNmpTvfve76dmzZ/7whz/k8ssvz7hx\n4zJw4MA89NBDtah++OGHs+22266yrLGxMV/4whfyhS98Icnqw3Vdae/9aENnvqAcl47A+/DWyxKe\nf/757LTTTvnZz36WYcOGZeDAgbn22mvz2GOPZcyYMRkwYMAqZ3puvPHGHHzwwRk4cGCOP/74zJkz\nJ0lSVVWmTp2aIUOGZM8998yYMWPy1FNPrbL9Cy+8MA8//HDOPvvsNDY21l7/kUceybhx47LXXntl\n3LhxeeSRR97xPQwfPjw//OEPM2rUqAwcODBf//rXs3Tp0trj99xzTw477LAMGDAgRx55ZJ588smV\n1p02bVrGjBmT/v3757jjjssDDzxQG8+f//znLFq0KF/72tcyePDg7L///vn3f//3vP7660neiLMj\njzwyU6dOzaBBg3LJJZestGzAgAE54IAD8sgjj+Smm27KsGHDMmTIkEyfPv0d389zzz2XY445Jo2N\njZk4cWLmz59fe+zN71Fra2tOO+20zJgxI1deeWUaGxvz05/+NN/4xjcye/bsNDY25uKLL37X77+1\ntTXNzc354he/mMGDB2f48OErXT5zySWX5OSTT87Xvva1NDY2ZvTo0Xn88ceTJFOmTMncuXNz4okn\nprGxMZdffvk7vsckqaurS9++fXPyySdnwoQJOe+889b4/Df927/9W8aOHZsTTjghvXr1Sl1dXXbb\nbbd8//vfT5IMGDAgDz/8cO35Dz/8cD73uc+tsmzAgAFt2t7b3XXXXRk9enQGDBiQY489Nn/6059q\nj63NfbG1tTXTpk3LgQcemMbGxowaNSp33HFHkuRPf/pTzjzzzNr3+s33ctppp+XCCy+sveb111+f\nESNGZO+9986JJ56Y5ubm2mM77bRTrr322owcOTIDBgzIt771rbz5Qcv//d//nWOOOSZ77bVXBg0a\nlMmTJ7/n+bjyyiszZsyY7LXXXpk8efJK87Em5557boYNG5Y999wzn/jEJ1b6/l1yySX50pe+lK9+\n9avZc889M3369Lz22ms59dRTM3DgwBx88MG5/PLLs99++9XWWdN+/XZvnccHHngg++23Xy6//PIM\nGTIkQ4cOzZ133pl77703Bx10UPbee+9cdtlltXUfe+yxHHHEERkwYECGDh2as88+O8uWLas9PmvW\nrBx00EHZa6+9ctZZZ+WYY47JDTfcUHv8/f5MhbWuAtpk//33r37961+vtOziiy+uvvKVr1RVVVXP\nPfdcteOOO1bf/OY3q9dee6267777qt12262aNGlS9de//rVqamqqBg8eXD3wwANVVVXVHXfcUR14\n4IHV008/XS1fvrz6wQ9+UB1xxBFVVVXVzJkzq8MPP7xasGBB9frrr1dPP/101dzcvNpxHXPMMdX1\n119f+3r+/PnVgAEDqunTp1fLly+vfvGLX1QDBgyoXnrppXd8X6NHj67mzp1bzZ8/vzriiCOqCy64\noKqqqvrDH/5QDR48uJo9e3bV2tpa3XTTTdX+++9fLV26tLbuoYceWs2dO7d69dVXVzueKVOmVCee\neGK1aNGi6rnnnqtGjhxZe/xnP/tZtfPOO1c//vGPq+XLl1evvvpqbdmNN95Ytba2VhdccEE1bNiw\n6qyzzqqWLl1a3XfffVX//v2rV155ZbXv55/+6Z+qqVOnVkuXLq0efPDBqn///qt8j5YvX15VVVWd\neuqptff65niOPPLI2tfv9v2vWLGiOvzww6tLLrmkWrp0afWXv/ylGj58eDVz5sza/rLbbrtVv/rV\nr6rW1tbq/PPPryZMmLDS9+Lt+9hb3X///dXHPvaxVZb/5je/qXbaaadq8eLFKy3fcccdq2effbb2\n9ZIlS6p//Md/rH7729++4zaef/75aqeddqrmz59frVixoho8eHD16quvVvvtt19t2Z577lk9+OCD\nK6339rlbnWeeeabaY489qlmzZlXLli2rpk2bVh144IErzefa3BdvvfXWqqmpqVqxYkV1yy23VHvs\nsUftOFrdeN+6P/zmN7+p9t577+r3v/99tXTp0urss8+ujjrqqJXm9oQTTqgWLFhQzZkzpxo0aFB1\n7733VlVVVV/+8perf//3f69WrFhRvfbaa9VDDz30nudj3LhxVVNTUzV//vzq4x//eHXNNdes9rXe\n/n5mzJhRvfTSS9Xy5curK6+8stpnn32q1157raqqN/bDXXbZpbrjjjuqFStWVK+++mp13nnnVUcf\nfXT18ssvVy+88EJ1yCGH1Pa1v7Vfv91b5/H++++vdt555+qSSy6pli1bVl133XXVoEGDqlNOOaVa\ntGhR9dRTT1Uf/ehHq7/85S9VVVXV448/Xj366KPV8uXLq+eee676+Mc/Xl111VVVVVXVvHnzqsbG\nxuq2226rli9fXv3oRz+qdtlll9rPk7X1MxXWJme0YS076aST0rlz5wwdOjSbbrppDjnkkGy++eZp\naGjIgAED8v/+3/9Lkvz0pz/NCSeckO222y719fU58cQT88QTT2TOnDmpr6/P4sWL88wzz6Sqqmy3\n3Xbp06dPm7b/q1/9Kttss03Gjh2b+vr6HHLIIdl2221zzz33vOM6Rx99dLbYYov06NEjkyZNql1b\ne9111+WII47IHnvskY4dO+bwww/PRhttlNmzZ9fWPfbYY7PFFlvUrs19qxUrVuTWW2/NV77ylWy2\n2WbZeuutM3HixPz85z+vPadPnz459thjU19fX3uNrbfeOuPGjUvHjh0zatSovPDCCznppJPSqVOn\nDB06NJ06dcpf/vKXVbY3d+7cPP744zn55JPTqVOnDBw4MMOHD2/TvK3Ou33/jz/+eF566aV84Qtf\nSKdOndKvX7/80z/9U2699dba8/faa68MGzYsHTt2zGGHHbbSWdn3qk+fPqmqKosWLVrj8xYuXJjX\nX389vXv3fsfnbLXVVtlyyy3z8MMP58knn8w222yTjTfeOHvuuWdt2fLly7PHHnu863HeeuutGTZs\nWPbdd99stNFGOf744/Paa6+tdLnL2twXDz744DQ0NKRDhw4ZNWpUttlmmzz22GNtGusvfvGLjBs3\nLrvuums6deqUU045JbNnz87zzz9fe87nPve5dOvWLVtuuWUGDRpU+16+eQlVS0tLOnfu/I5n/9sy\nH8cee2waGhrSo0eP7L///nniiSfaNP7DDjssPXv2TH19fT7zmc9k2bJl+fOf/1x7vH///jnwwAPT\noUOHbLzxxvnlL3+Zf/7nf0737t3Tt2/fHHfccbXntmW/XpP6+vpMmjQpG220UUaNGpX58+fnuOOO\ny2abbZYddtgh22+/ff74xz8mSXbbbbf0798/9fX12XrrrXPEEUfkoYceSpLMnDkzO+ywQ0aOHJn6\n+vocd9xx+bu/+7vadkr9TIX3w0VZsJZtvvnmtf/u3LnzKl8vWbIkyRtROHXq1Hz3u9+tPV79z3W3\nQ4YMydFHH52zzz47c+bMyciRI3Pqqadms802+5vbb2lpyZZbbrnSsi233HKlf/Z+uy222GKl57a0\ntNTGOGPGjPznf/5n7fHly5fXHn/7um83f/78LF++fKXxvH0sffv2XWW9t87Zm9H01v+hdu7cOYsX\nL15lvZaWlnTr1m2la6y33HLLvPDCC+84xjV5t+9/zpw5aWlpWSmsVqxYsdLXb30fG2+8cZYuXfq+\nr5FtaWlJXV1dunbtusbndevWLR06dMiLL76Y7bbb7h2f9+blI1tssUVt7HvttVdt2e67755OnTq9\np3G+dV/o0KFDtthii5X2h7W5L86YMSNXXXVV7fKBJUuWrHQp0d8a66677lr7ukuXLunRo0eam5uz\n9dZbJ8lKv7BssskmtX1yypQp+f73v5/x48ene/fumThx4mrvYtOW+Xj7Nt76ftfkyiuvzI033ljb\nN1555ZWV3vvbj7uWlpaV5u+tj7dlv16THj161P6I/M3j+e0/F9+cuz//+c/5zne+k9///vd59dVX\ns2LFitr3oaWlZaVxvXn51JtK/UyF90NowzqyxRZb5MQTT8yhhx662sePO+64HHfccZk3b14mT56c\nK664Yo3Xer6pT58+mTt37krLXnjhhXzsYx97x3XeGqJz586tnel5c4yTJk16x3Xf/EPC1enZs2c2\n2mijzJ07N9tvv31tWw0NDW1a/93q3bt3Fi5cmCVLltRie+7cue95G+/2/W+xxRbZeuutc/vtt7+n\n7b1Xd9xxR3bZZZe/+Uecm2yySfr375/bb789gwcPfsfnDRw4MD/96U+z1VZb5ROf+ESSN+J7+vTp\n2Wqrrd7z9dl9+vRZ6brYqqpW2R/W1r44Z86cfOMb38iPfvSjNDY21v4FYXXPfaexvhnoyRuR/vLL\nL6801nfSu3fvnHvuuUneuJ594sSJGThw4Ep/lPrmNv7WfLwXDz/8cK644or86Ec/yg477JAOHTpk\n4MCBtWvIk1Xff+/evdPU1FQ7TpuammqPted+fdZZZ2WXXXbJ9773vWy22Wb50Y9+lNtuu602xrf+\nElJV1SrjLPEzFd4Pl47AOnLkkUdm2rRp+f/+v/8vSbJo0aL88pe/TPLGHwT913/9V5YvX55NNtkk\nnTp1SocOqz9c/+7v/i7PPfdc7ethw4bl2WefzS9+8Yu0trbm1ltvzdNPP53/9b/+1zuO5ZprrklT\nU1NefvnlXHbZZbW7S0yYMCE//elP81//9V+pqipLlizJr371q7zyyitteo8dO3bMxz/+8Vx44YV5\n5ZVXMmfOnFx11VXv+D/C92urrbbKbrvtlksuuSTLli3Lww8/vMZLZv6Wd/v+d99993Tp0iXTpk3L\na6+9lhUrVuSpp55q8+UKb/9ersmbZ+ouvfTS3HDDDTnllFPatN6UKVMyffr0XHHFFbUznE8++WS+\n/OUv154zYMCAPPHEE3nooYey5557Jkl23HHHPP/883nggQcycODANm3r7Q4++ODce++9+e1vf5vl\ny5fnf//v/51OnTqtdBvNtbUvvvrqq6mrq0uvXr2SJD/72c9qx1ryxhnV5ubmlf7Q7q0OOeSQ3HTT\nTXniiSeybNmyXHDBBdl9991rZ7PX5Je//GUtALt37566urrVHr9tmY/3YvHixenYsWN69eqV1tbW\nXHrppX/zmD344IPzwx/+MAsWLEhzc/NK/3Lwfvfrdzv2Ll26pEuXLvnTn/600l1shg0blj/+8Y+5\n884709ramp/85Cf561//Wnt8bf1MhbXJGW1YR0aMGJHFixfnlFNOyZw5c9K1a9fss88+Ofjgg7N4\n8eJMnTo1zz//fO265OOPP361r3PcccfltNNOy7XXXpvDDjss3/jGN3LZZZdl6tSpOeuss7LNNtvk\nsssuqwXH6hxyyCH5zGc+k5aWlhxwwAG1s4Yf/ehHc8455+Tss8/Of//3f9eu1X03ZzS/+c1v5pxz\nzsmBBx6Yzp07Z8KECRk3bty7m6x34Xvf+15OPfXUDBo0KP3798/YsWOzcOHC9/Ra7/b9d+zYMZdd\ndlm++93v5oADDsiyZcvykY98pM1nzU444YSce+65Oe+88zJp0qTVfs9bWlrS2NiYqqqy2WabZc89\n98z/+T//J/3792/TNvbcc89cffXVufjii/Mf//Ef6dixY7bZZpscffTRted85CMfSa9evdKzZ890\n69YtyRuXNey+++75zW9+855DcNttt815552Xc845J83Nzdl5551z2WWXrXQZytraF7fffvt85jOf\nyZFHHpm6urqMHTu29ktDkgwePDjbb799hg4dmrq6ujzwwAMrrb/PPvvk5JNPzhe/+MUsXLgwjY2N\nK92RZE0ef/zxTJ06Na+88ko233zznH766enXr997mo/3YujQofnYxz6Wgw46KJtuumk+9alPrfES\nr+SNvy0588wzc8ABB6R3794ZM2ZMbrrppiTvf79+N0499dR885vfzJVXXpmdd945o0aNyv33358k\n6dWrV77//e/n29/+dk499dSMGTMmu+22WzbaaKMka+9nKqxNddVb/y0J+NBxf3DWF/bF9cc111yT\nW2+9daUz2+ub119/Pfvtt1/OP//8NV4KBeuSfzcBgA+5lpaW/O53v8vrr7+eZ555JldddVUOPPDA\ndT2sVdx3331ZuHBhli1bVrv/dlv/NQfWBZeOAMCH3PLly3PmmWfm+eefT9euXTN69OgcddRR63pY\nq5g9e3a++tWvZtmyZdl+++3zgx/8YLW3FoX1hUtHAACgAJeOAABAAR/IS0defHHNn472QdGz56aZ\n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\nbQAAKEBoAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAA\nChDaAABQgNAGAIAChDYAABQgtAEAoAChDQAABQhtAAAoQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2\nAAAUILQBAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAF\nCG0AACigeGivWLEiY8eOzT//8z8nSZ577rlMmDAhI0aMyOTJk7Ns2bIkybJlyzJ58uSMGDEiEyZM\nyPPPP197jR/+8IcZMWJEDjrooNx3332lhwwAAO9b8dD+8Y9/nO2226729fnnn59Pf/rTueOOO9Kt\nW7fceOONSZIbbrgh3bp1yx133JFPf/rTOf/885MkTz/9dG655ZbccsstueKKK/Ktb30rK1asKD1s\nAAB4X4qGdlNTU371q19l/PjxSZKqqnL//ffnoIMOSpIcfvjhueuuu5Ikd999dw4//PAkyUEHHZTf\n/va3qaoqd911V0aPHp1OnTqlX79+2WabbfLYY4+VHDYAALxvRUN76tSpmTJlSjp0eGMz8+fPT7du\n3VJfX58k6du3b5qbm5Mkzc3N2WKLLZIk9fX16dq1a+bPn5/m5ub07du39poNDQ21dQAAYH1VX+qF\n77nnnvTq1Su77bZbHnjggVKbWa2ePTdNfX3Hdt3mutK7d9d1PYT1knlZ1Xo/J106t/8m23GbXdb3\n+f8f6/1+sg5sEHPSzsePY2f1Noh9pZ192OekWGg/8sgjufvuuzNz5swsXbo0r7zySr797W9n4cKF\naW1tTX19fZqamtLQ0JDkjTPVL7zwQvr27ZvW1tYsWrQoPXv2TENDQ5qammqv29zcXFvnncyfv6TU\n21qv9O7dNS++uGhdD2O9Y15WtSHMyaaLl7br9rp06ZzF7bjNJev5/Ccbxn7S3jaUOWnP48exs3ob\nyr7Snj4sc7KmXyaKXTryla98JTNnzszdd9+dCy64IIMHD873vve9DBo0KLfddluSZPr06Rk+fHiS\nZPjw4Zk+fXqS5LbbbsvgwYNTV1eX4cOH55ZbbsmyZcvy3HPP5dlnn83uu+9eatgAALBWtPt9tKdM\nmZKrrroqI0aMyMsvv5wJEyYkScaPH5+XX345I0aMyFVXXZWvfvWrSZIddtghBx98cEaNGpXPfvaz\nOeOMM9Kx44fjshAAADZcxS4deatBgwZl0KBBSZJ+/frVbun3Vp07d87FF1+82vUnTZqUSZMmFR0j\nAACsTT4b9NcLAAAgAElEQVQZEgAAChDaAABQgNAGAIAChDYAABQgtAEAoAChDQAABQhtAAAoQGgD\nAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQBAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKENoAAFCA\n0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAAChDaAABQgNAGAIAChDYAABQgtAEA\noAChDQAABQhtAAAoQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQBAKAAoQ0AAAUIbQAAKEBo\nAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAAChDaAABQ\ngNAGAIAChDYAABQgtAEAoAChDQAABQhtAAAoQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQB\nAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChA\naAMAQAFCGwAAChDaAABQgNAGAIAChDYAABQgtAEAoAChDQAABdS39YmvvfZaXnzxxXTu3Dl9+vQp\nOSYAANjgrTG0X3/99cyYMSM33HBDnnzyyWy22WZZtmxZ6uvrc+CBB+bTn/50PvKRj7TXWAEAYIOx\nxtA+8sgj09jYmK9//evZdddd07FjxyTJvHnzct999+WMM87IkUcemdGjR7fLYAEAYEOxxtC+7LLL\n0qtXr1WWb7755hk7dmzGjh2bl156qdjgAABgQ7XGP4ZcXWTPmzcvs2fPXuNzAADgw65Ndx056qij\nsmjRoixcuDBjx47N6aefnu9+97ulxwYAABusNoX2kiVL0rVr19xzzz0ZM2ZMfvGLX2TWrFmlxwYA\nABusNoX2smXLkiQPPPBA9t1333To0KH2h5EAAMCq2hTae++9d0aNGpXf/e532XvvvbNw4cJ06OCz\nbgAA4J206QNrzjzzzDz55JPp169fNtpooyxatCjnnntu6bEBAMAGq02hXVdXl3/4h39IU1NTmpqa\nkiSdOnUqOjAAANiQtSm0f/zjH+fCCy9M9+7da5eM1NXV5a677io6OAAA2FC1KbSvvvrq/N//+3/T\n0NBQejwAAPCB0Ka/aOzbt6/IBgCAd6FNZ7S/+MUv5vTTT8+wYcPSuXPn2vJhw4YVGxgAAGzI2hTa\n99xzT+655548++yzK12jLbQBAGD12hTad9xxR+6+++5svPHGpccDAAAfCG26Rrtfv36pr29TkwMA\nAGnjGe1tttkmn/rUp3LggQeudP/so48+utjAAABgQ9am0F6+fHn+/u//Pk899VTp8QAAwAdCm0L7\nX//1X0uPAwAAPlDWeI3273//+zWuvGzZsvzpT39aqwMCAIAPgjWG9rRp0/LZz342M2bMyJ///Ocs\nWrQof/3rX/PQQw/lggsuyIQJE9LS0rLadZcuXZrx48fn0EMPzejRo3PxxRcnSZ577rlMmDAhI0aM\nyOTJk7Ns2bIkb0T75MmTM2LEiEyYMCHPP/987bV++MMfZsSIETnooINy3333ra33DgAAxazx0pGL\nL744jz32WK677rr84Ac/SFNTUzbZZJPsuOOOOfDAA/OTn/wkm2222WrX7dSpU66++up06dIly5cv\nz1FHHZX99tsvV111VT796U9n9OjROeOMM3LjjTfmqKOOyg033JBu3brljjvuyC233JLzzz8/F110\nUZ5++unccsstueWWW9Lc3JyJEyfmtttuS8eOHYtMCAAArA1/8xrt3XffPbvvvvu7fuG6urp06dIl\nSdLa2prW1tbU1dXl/vvvz/e+970kyeGHH55LL700Rx11VO6+++584QtfSJIcdNBBOfvss1NVVe66\n666MHj06nTp1Sr9+/bLNNtvkscceS2Nj47seEwAAtJc23Uf7vVqxYkUOO+yw7LPPPtlnn33Sr1+/\ndOvWrXZP7r59+6a5uTlJ0tzcnC222CJJUl9fn65du2b+/Plpbm5O3759a6/Z0NBQWwcAANZXRT+F\npmPHjrn55puzcOHCnHTSSXnmmWdKbq6mZ89NU1//4bi0pHfvrut6COsl87Kq9X5OunRu/0224za7\nrO/z/z/W+/1kHdgg5qSdjx/HzuptEPtKO/uwz0m7fNxjt27dMmjQoMyePTsLFy5Ma2tr6uvr09TU\nlIaGhiRvnKl+4YUX0rdv37S2tmbRokXp2bNnGhoa0tTUVHut5ubm2jrvZP78JUXfz/qid++uefHF\nRet6GOsd87KqDWFONl28tF2316VL5yxux20uWc/nP9kw9pP2tqHMSXseP46d1dtQ9pX29GGZkzX9\nMlHs0pGXXnopCxcuTJK89tpr+c1vfpPtttsugwYNym233ZYkmT59eoYPH54kGT58eKZPn54kue22\n2zJ48ODU1dVl+PDhueWWW7Js2bI899xzefbZZ9/TNeMAANCe2nRGe968efnXf/3XvPDCC/nJT36S\nJ598Mo8++mg++clPvuM6LS0tOe2007JixYpUVZWPf/zj2X///bP99tvny1/+ci666KLsvPPOmTBh\nQpJk/PjxmTJlSkaMGJHu3bvnwgsvTJLssMMOOfjggzNq1Kh07NgxZ5xxhjuOAACw3mtTaH/jG9/I\nfvvtl2uuuSZJsu2222bKlClrDO1//Md/zIwZM1ZZ3q9fv9x4442rLO/cuXPtXttvN2nSpEyaNKkt\nQwUAgPVCmy4daW5uzic/+cnameROnTqlQ4eiNywBAIANWptq+c3b8b1p4cKFqaqqyIAAAOCDoE2X\njowYMSJnnHFGFi9enJtuuinXXHNNxo0bV3psAACwwWpTaH/uc5/Lz3/+8yxcuDD33ntvjj322Bx2\n2GGlxwYAABusNt9H+9BDD82hhx5aciwAAPCB0ebb+/3nf/5n/vKXv6S1tbW2/Pvf/36xgQEAwIas\nTaH9+c9/PrvsskuGDBniHtYAANAGbQrtV199NWeeeWbpsQAAwAdGm27vt8cee+SPf/xj6bEAAMAH\nRpvOaB955JE55phj0rdv33Tu3Lm2fHWf8AgAALQxtKdMmZITTzwxu+yyi2u0AQCgDdoU2p07d87x\nxx9feiwAAPCB0aZrtD/2sY9l5syZpccCAAAfGG06o3399ddn2rRp6dKlSzp16pSqqlJXV5ff/va3\npccHAAAbpDaF9s9+9rPS4wAAgA+UNoX2VlttVXocAADwgbLG0J4yZUrOO++8jBs3LnV1das87vZ+\nAACwemsM7U996lNJklNPPbVdBgMAAB8Uawzta665JlOnTs3ee+/dXuMBAIAPhDXe3u+JJ55or3EA\nAMAHSpvuow0AALw7a7x05KmnnsqQIUNWWe4+2gAAsGZrDO1/+Id/yLRp09prLAAA8IGxxtDu1KmT\ne2gDAMB7sMZrtDfaaKP2GgcAAHygrDG0r7/++vYaBwAAfKC46wgAABQgtAEAoAChDQAABQhtAAAo\nQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQBAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKENoA\nAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAAChDaAABQgNAGAIAChDYAABQg\ntAEAoAChDQAABQhtAAAoQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQBAKAAoQ0AAAUIbQAA\nKEBoAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAAChDa\nAABQgNAGAIAChDYAABQgtAEAoAChDQAABQhtAAAoQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAU\nILQBAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0A\nAChAaAMAQAFCGwAAChDaAABQgNAGAIAChDYAABQgtAEAoIBiof3CCy/k2GOPzahRozJ69OhcffXV\nSZKXX345EydOzMiRIzNx4sQsWLAgSVJVVc4999yMGDEiY8aMyR/+8Ifaa02fPj0jR47MyJEjM336\n9FJDBgCAtaZYaHfs2DGnnXZabr311lx33XW55ppr8vTTT2fatGkZMmRIbr/99gwZMiTTpk1Lksyc\nOTPPPvtsbr/99pxzzjk566yzkrwR5pdeemmuv/763HDDDbn00ktrcQ4AAOurYqHdp0+f7LrrrkmS\nzTbbLNtuu22am5tz1113ZezYsUmSsWPH5s4770yS2vK6urr0798/CxcuTEtLS2bNmpV99903PXr0\nSPfu3bPvvvvmvvvuKzVsAABYK9rlGu3nn38+TzzxRPbYY4/Mmzcvffr0SZL07t078+bNS5I0Nzen\nb9++tXX69u2b5ubmVZY3NDSkubm5PYYNAADvWX3pDSxevDhf+tKX8i//8i/ZbLPNVnqsrq4udXV1\na32bPXtumvr6jmv9dddHvXt3XddDWC+Zl1Wt93PSpXP7b7Idt9llfZ///7He7yfrwAYxJ+18/Dh2\nVm+D2Ffa2Yd9ToqG9vLly/OlL30pY8aMyciRI5Mkm2++eVpaWtKnT5+0tLSkV69eSd44U93U1FRb\nt6mpKQ0NDWloaMiDDz5YW97c3Jy99957jdudP39JgXez/undu2tefHHRuh7Gese8rGpDmJNNFy9t\n1+116dI5i9txm0vW8/lPNoz9pL1tKHPSnsePY2f1NpR9pT19WOZkTb9MFLt0pKqqnH766dl2220z\nceLE2vLhw4dnxowZSZIZM2bkgAMOWGl5VVWZPXt2unbtmj59+mTo0KGZNWtWFixYkAULFmTWrFkZ\nOnRoqWEDAMBaUeyM9u9+97vcfPPN2XHHHXPYYYclSU455ZSccMIJmTx5cm688cZsueWWueiii5Ik\nw4YNy7333psRI0Zkk002ydSpU5MkPXr0yOc///mMHz8+SXLSSSelR48epYYNAABrRbHQHjBgQP74\nxz+u9rE376n9VnV1dTnzzDNX+/zx48fXQhsAADYEPhkSAAAKENoAAFCA0AYAgAKENgAAFCC0AQCg\nAKENAAAFCG0AAChAaAMAQAFCGwAAChDaAABQgNAGAIAChDYAABQgtAEAoAChDQAABQhtAAAoQGgD\nAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQBAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKENoAAFCA\n0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAAChDaAABQgNAGAIAChDYAABQgtAEA\noAChDQAABQhtAAAoQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQBAKAAoQ0AAAUIbQAAKEBo\nAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAAChDaAABQ\ngNAGAIAChDYAABQgtAEAoAChDQAABQhtAAAoQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQB\nAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChA\naAMAQAFCGwAAChDaAABQgNAGAIAChDYAABQgtAEAoAChDQAABQhtAAAoQGgDAEABQhsAAAoQ2gAA\nUIDQBgCAAoQ2AAAUILQBAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0\nAQCggGKh/fWvfz1DhgzJIYccUlv28ssvZ+LEiRk5cmQmTpyYBQsWJEmqqsq5556bESNGZMyYMfnD\nH/5QW2f69OkZOXJkRo4cmenTp5caLgAArFXFQvsTn/hErrjiipWWTZs2LUOGDMntt9+eIUOGZNq0\naUmSmTNn5tlnn83tt9+ec845J2eddVaSN8L80ksvzfXXX58bbrghl156aS3OAQBgfVYstAcOHJju\n3buvtOyuu+7K2LFjkyRjx47NnXfeudLyurq69O/fPwsXLkxLS0tmzZqVfffdNz169Ej37t2z7777\n5r777is1ZAAAWGvq23Nj8+bNS58+fZIkvXv3zrx585Ikzc3N6du3b+15ffv2TXNz8yrLGxoa0tzc\n/De307Pnpqmv77iWR79+6t2767oewnrJvKxqvZ+TLp3bf5PtuM0u6/v8/4/1fj9ZBzaIOWnn48ex\ns3obxL7Szj7sc9Kuof1WdXV1qaurK/La8+cvKfK665vevbvmxRcXrethrHfMy6o2hDnZdPHSdt1e\nly6ds7gdt7lkPZ//ZMPYT9rbhjIn7Xn8OHZWb0PZV9rTh2VO1vTLRLvedWTzzTdPS0tLkqSlpSW9\nevVK8saZ6qamptrzmpqa0tDQsMry5ubmNDQ0tOeQAQDgPWnX0B4+fHhmzJiRJJkxY0YOOOCAlZZX\nVZXZs2ena9eu6dOnT4YOHZpZs2ZlwYIFWbBgQWbNmpWhQ4e255ABAOA9KXbpyCmnnJIHH3ww8+fP\nz3777ZcvfvGLOeGEEzJ58uTceOON2XLLLXPRRRclSYYNG5Z77703I0aMyCabbJKpU6cmSXr06JHP\nf/7zGT9+fJLkpJNOSo8ePUoNGQAA1ppioX3BBResdvnVV1+9yrK6urqceeaZq33++PHja6ENAAAb\nCp8MCQAABQhtAAAoQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQBAKAAoQ0AAAUIbQAAKEBo\nAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAAChDaAABQ\ngNAGAIAChDYAABQgtAEAoAChDQAABQhtAAAoQGgDAEABQhsAAAoQ2gAAUIDQBgCAAoQ2AAAUILQB\nAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKqF/XAwAAoLx/e3Bqu26vS5fOWbx4abts62t7/0u7bOfd\nckYbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAACvDJkABsUNrz\n0+3a85PtkvX30+2A98YZbQAAKEBoAwBAAUIbAAAKENoAAFCA0AYAgAKENgAAFCC0AQCgAKENAAAF\nCG0AAChAaAMAQAFCGwAAChDaAABQgNAGAIAChDYAABQgtAEAoAChDQAABQhtAAAoQGgDAEABQhsA\nAAoQ2gAAUIDQBgCAAoQ2AAAUILQBAKAAoQ0AAAUIbQAAKEBoAwBAAUIbAAAKENoAAFCA0AYAgAKE\nNgAAFCC0AQCgAKENAAAFCG0AAChAaAMAQAFCGwAAChDaAABQgNAGAIAChDYAAP+/9u49KKrzjOP4\nV8iCqJRIiibVTmPqpWpwrIOx6ngJFyEsC15QGwWj0TSWGJPReIlp0XFirFSdMXY61anTTjuOja0X\npEFq1ca0VTHSZjBYm9rES2yiI6DIdWF5+wfjCbgIIrsLa36fv2T3nOe878N5nee8nHNe8QIV2iIi\nIiIiXqBCW0RERETECx7q6AaIiIiIeFpWVpBPj9e9O1RU+OaYy5c7fXIcaT/NaIuIiIiIeIFmtEVE\nOqkHeUYONCsnIg8+zWiLiIiIiHiBCm0RERERES9QoS0iIiIi4gUqtEVEREREvECFtoiIiIiIF6jQ\nFhERERHxAr3ez8O6Zb3lu4N1D6ZbRY3PDle5fJXPjiUiIiLi7zSjLSIiIiLiBSq0RURERES8QIW2\niIiIiIgX+E2h/f777xMfH09cXBzbt2/v6OaIiIiIiLTILx6GdLlcrF27ll/96lf07t2b1NRUoqOj\n6d+/f0c3TeS+ZJ3y4UOzQPfuwVT46MHZ5U/poVkRERHwk0K7sLCQb33rW3zzm98EwG63c+TIERXa\nfiIrK8inx+veHSoqfHPM5cudPjmOiIiI+J8uxhjT0Y1oTV5eHn/9619Zt24dAPv376ewsJDMzMwO\nbpmIiIiISPP85h5tERERERF/4heFdu/evfniiy+sn69evUrv3r07sEUiIiIiIi3zi0I7MjKSCxcu\ncPnyZZxOJ++++y7R0dEd3SwRERERkbvyi4chH3roITIzM1mwYAEul4tp06YxYMCAjm6WiIiIiMhd\n+cXDkCIiIiIi/sYvbh0REREREfE3KrRFRERERLxAhfZXwJYtWzh+/HhHN4OysjJ27tzZ5LMNGzZg\nt9vZsGGDT9rwxhtvcP78eZ8c614oJ963d+9e1q5d26Z9fvGLX7S6zcqVK8nLy7vfZnlMW86hrVu3\nsmPHjnbFbk56ejpnzpy557jeppx4zoM8fnSeuFNOPE+F9lfAK6+8wpgxYzq6GZSVlbFr164mn+3e\nvZsDBw6wYsUKn7Rh3bp1nWpFUeWkc9q2bVtHN+GeefMcai62P1BOOpa/jB+dJ+6UE89Toe1Bn332\nGc888ww/+tGPsNvtPP/881RXVwMNV2hvvvkmKSkpJCUlUVhY6LZ/TU0Nr7/+Og6Hg8mTJ3Py5Emg\nYUZh0aJFzJ8/n0mTJpGVlWXt87e//Y2ZM2cyZcoUFi9eTEVFhVvcxjMH0dHRbNq0iZSUFKZOnUpR\nURHz588nNjbWGgD19fWsWbOGhIQE5s2bxwsvvOCRmYdNmzZx6dIlUlJS2LBhAwsXLqSyspKpU6eS\nm5vbZNsbN26QkZGBw+FgxowZnDt3Dmi4gn799ddJT08nJiaG3/zmN9Y+2dnZpKamkpKSQmZmJi6X\ny60Nja+Uv/vd71pX6nPnzqWwsNCKe+TIEQCqqqp45ZVXSExM5KWXXmL69OkevdJWTlrX3nEF8Pnn\nn5Oens6kSZP42c9+Zn2ekZHB1KlTsdvtvPPOOwBs3LiR6upqUlJSWLp0KdCwGq3D4SA5OZlly5ZZ\n+58+fZrvf//7xMTEdNjsXFvOIYBz584xc+ZMJk2axO7duwGoqKjgueeeY8qUKTgcDg4fPtxsbIDt\n27dbudi4caMVNy8vj9TUVOLj4zl9+rQPen53ysmXNH7uTueJO+XEC4x4zOXLl83gwYPN2bNnjTHG\nLF682Ozfv98YY0xaWpp54403jDHGnDp1ytjtdrf9d+zYYVauXGmMMeb8+fNmwoQJprq62uzZs8dE\nR0ebsrIyU11dbSZOnGj+97//meLiYjNr1ixTUVFhjDFm27ZtZuvWrW5xV6xYYQ4ePGiMMebpp582\nO3fuNMYYs27dOpOUlGRu3bpliouLzejRo40xxhw8eNAsWLDAuFwuc+3aNRMVFWXt39783Nnv4cOH\nN7vt2rVrrb4cP37cJCcnG2OMefvtt83MmTNNTU2NKS4uNk899ZRxOp3m/Pnz5sUXXzROp9MYY8zq\n1avNvn373OKmpaWZwsJCY4wxAwcONO+9954xxpiMjAwzb94843Q6zb/+9S/reL/85S/Nj3/8Y2OM\nMf/+97/N4MGDrf09QTlpXXvH1Z49e8zYsWNNSUmJqaqqMna73WpvaWmpMcZYn5eUlBhjmv4OPv74\nYzNp0iRTXFzcZJ8VK1aYl19+2bhcLvOf//zHxMbGeqP7rWrLOfT2228bh8NhqqqqTHFxsRk/frz5\n4osvTG1trbl165Yxxpji4mITGxtr6uvr3WK/9957ZubMmaaystIY82Uu0tLSzPr1661tnnvuOU93\ns02Uky9p/NydzhN3yonn+cV7tP1J3759GTx4MABDhw7lypUr1nd2ux2AkSNHUl5eTllZGV/72tes\n7wsKCkhLSwPg29/+Nt/4xjf49NNPARg9ejShoaHWd1euXOHWrVucP3+eZ599FoDa2lqGDx/eahtj\nYmIAGDhwIJWVlfTo0QOAoKAgysrKKCgoICEhgYCAACIiIhg1alS7cnI/CgoK2Lp1K9DQ9xs3blBe\nXg7AhAkTCAoKIjw8nPDwcIqLizlx4gQfffQRqampAFRXV/PII4+0eAybzcb48eOBhlwEBQVhs9kY\nOHCg9XsrKChgzpw51jaDBg3ySn/vxVc5J+0ZVwBjxoyhZ8+eAMTFxVFQUEBkZCS//e1v+fOf/ww0\nzNpdvHjR2u62kydPkpCQQHh4OAAPP/yw9V1sbCwBAQH079+f69eve7jX3hETE0PXrl3p2rUro0aN\n4syZM0yYMIHNmzfzwQcfEBAQwNWrV5vtz4kTJ5g6dSohISFA01zExcUB7r8ff/Cg50TjxzMe9PPk\nfignrVOh7WFBQUHWvwMDA6mpqbF+7tKlS5Nt7/y5LXFdLhfGGMaOHcvmzZvb1EabzQZAQEBAk7gB\nAQHU1dW1KVZHuDMXdXV1GGOYMmWK9afKe2Gz2azfQeNcBAQENHuLRWf2oOekveOquW3y8/M5fvw4\n77zzDiEhIaSnpzeJ29Z2+Yvm8pOTk0NJSQl79+7FZrMRHR1937no6HPlfjzoOdH48YwH/Ty5H8pJ\n63SPtg/dvr/p9OnThIaGWjPUt0VFRZGTkwPAp59+yueff84TTzxx13jDhw/nH//4BxcvXgSgsrLS\nmgFvjxEjRnDo0CHq6+u5fv06p06dandMgO7duzd7D3lzoqKiOHDgAAD5+fn07NnTmnlvzujRo/nT\nn/5EcXEx0HA/syeugkeMGMHBgwcBOH/+PB9//HG7YzamnLRfa+MK4O9//zs3btygurqaw4cPM2LE\nCG7dukVYWBghISH897//5cMPP7S2f+ihh6itrQXge9/7Hnl5eZSWlgINeexM2nIOARw5coSamhpK\nS0s5deoUkZGR3Lp1i0ceeQSbzcbJkyet8+TO2GPGjGHv3r1UVVUBnS8Xtykn9+6rPH50nrhTTjxP\nM9o+FBwczOTJk6mrq+Ott95y+37WrFmsWbMGh8NBYGAg69evb/GKPzw8nPXr17NkyRKcTicAr776\nKv369WtXO+Pj4zlx4gSJiYk89thjDBkypNn/fNuqZ8+ejBgxgqSkJMaNG9fiE8yLFi1i1apVOBwO\nQhnyD5sAAAo4SURBVEJC+MlPftJi7P79+/Pqq6/y/PPPU19fj81mIzMzkz59+rSrzbNmzWLlypUk\nJibyxBNP0L9/f4/k4jblpP1aG1cAw4YN4+WXX+bq1askJycTGRnJoEGD+N3vfsczzzxDv379mtx2\nNWPGDJKTkxkyZAibNm1i4cKFpKenExAQwJAhQ1rNvS+15RwCGDRoEHPmzKG0tJSMjAx69+6Nw+Hg\nhz/8IQ6HgyeffNK6wG8u9rlz55g2bRo2m40JEyawZMkSX3SzTZSTe/dVHj86T9wpJ56nJdh9JD09\nneXLlxMZGdnRTbknFRUVdO/endLSUqZPn86uXbuIiIjo6Gb5nMvloq6ujuDgYC5dusTcuXPJy8vz\nuz95elJnyom/jSuRzkTjR8T7NKMtzVq4cCFlZWXU1taSkZHxlSyyoeFVdnPmzLHueV69evVXusgG\n5UREROReaUZbRERERMQL9DCkdHrV1dWkpaV59MnjkpIS5s+f77F4HcHTeXE6ncyePdsv3jwj907j\nx53Gjoj4igpt6fT27NlDXFwcgYGBHosZHh5Or169KCgo8FhMX/N0XoKCghg9enSzq3+J/9L4caex\n86X8/HxWrlzZ0c3odJQXd8rJ/VGhLZ1eTk4OMTExLS4NHx0dTVZWFg6Hg9TUVOuVh42Xn4eGJcZv\ni4mJsV6n6I9u5wWaX8b2bssrb926lR07dlhxkpKS+Oyzz4CGBST8OSfiTuPHncZOyy5evMjcuXNJ\nTk5mypQpXLp0CWMMGzZsICkpCYfDYV1U5Ofnk56ezuLFi0lISGDp0qUYY3j//fdZvHixFTM/P58X\nX3yxo7rkEcqLO+WkdXoYUjo1p9PJ5cuX6du3L3l5eVy5coXc3FyKi4tJTExk2rRp1rahoaHk5OSw\nf/9+3nrrLbZt29Zi7MjISLZs2eLtLnhF47wcO3aMo0ePsnv3bkJCQpq8i7S6uprs7Gw++OADVq1a\nxR//+McW4w4YMIAzZ854u/niIxo/7jR2Wvfaa6/xgx/8gLi4OGpqaqivr+fQoUOcO3eO7OxsSktL\nSU1NJSoqCoCzZ8/y7rvv0qtXL5599lkKCgoYM2YMmZmZVFZW0q1bN3Jzc0lMTOzgnrWP8uJOOWmd\nCm3p1EpLS613NLe2NHxSUhLQsKTw+vXrW40dHh7OtWvXPN9oH2icl5aWsW1ueeWWBAYGYrPZKC8v\nb3ExHPEPGj/uNHYaTJ8+HafTSWVlJTdv3iQlJQXAel/27SWwg4ODgYbzx263ExgYyNe//nVGjhzJ\nmTNn6NGjB8OGDePRRx8F4Dvf+Q5XrlwhKiqKcePG8Ze//IX4+HiOHTvGsmXLOqazbaC8uFNO2keF\ntnRqXbt2tRbjuR+BgYHU19cDUF9fb61WBlBTU2P9x+Bv7jUvzS2d3DgngNvSuE6n02/zIk1p/LjT\n2Gnw+9//Hmj4M/2+ffusRWTKy8vbHOvOJd5vP2SamJjIzp07CQsL48knn/SLCxDlxZ1y0j66R1s6\ntbCwMFwuFzU1Na0uDX97WfDc3FzrXtI+ffpQVFQEwNGjR5sUChcuXGDAgAE+6olnNc5LS8vYNre8\ncp8+fTh79iwARUVF1j2m0DDb17NnT2w2mw97I96i8eNOY6dlPXr04NFHH+Xw4cNAw8VDVVUVUVFR\nHDx4EJfLRUlJCadPn2bYsGEtxnrqqac4e/Ysu3fv9vtbAZQXd8rJvdGMtnR6Y8eOpaCgoNWl4W/e\nvInD4SAoKIjNmzcDDUsBZ2RkkJyczLhx4+jWrZu1fX5+PhMnTvR1dzzmdl7Gjx9/12Vsm1teOT4+\nnuzsbOx2O8OGDePxxx+3Yvp7TsSdxo87jZ2WZWVlkZmZyZYtW7DZbGzZsoW4uDj++c9/kpKSQpcu\nXVi2bBkRERF88sknd40TGBjIxIkT2bdvHxs2bPBhD7xDeXGnnNwDI9LJffTRR+a1114zxhhTXl5u\njDGmpKTExMTEmGvXrhljjHn66adNcXFxm+LOmjXL3Lhxw7ON9aHGeWlOWlqaKSwsbFPMl156yXzy\nySftbZp0Iho/7jR2RMRXNKMtnd7QoUMZNWoULpfLY0vDl5SUMG/ePMLCwjzcWt9pnBdPvA/Y6XQS\nGxtLv379PNA66Sw0ftxp7IiIr2gJdhERERERL9DDkCIiIiIiXqBCW0REROQO1dXVpKWlWa+g84SS\nkhLmz5/vsXgdwdN5cTqdzJ49m7q6Oo/E62xUaIuIiIjcYc+ePcTFxXnkPv7bwsPD6dWrFwUFBR6L\n6WuezktQUBCjR4+2Xqn5oFGhLSIiInKHnJwcYmJiqK+vZ82aNSQkJDBv3jxeeOEF8vLyAIiOjiYr\nKwuHw0FqaioXL14EYOXKldY2gPVueoCYmBhycnJ82xkPup0XgO3bt+NwOEhOTmbjxo0ApKen8+ab\nb5KSkkJSUhKFhYUAbN26lR07dlhxkpKSrHfRx8bG+nVOWqJCW0RERKQRp9PJ5cuX6du3L4cOHeLK\nlSvk5uaSlZXFhx9+2GTb0NBQcnJySEtLs9653pLIyEi/ndFunJdjx45x9OhRdu/ezYEDB1iwYIG1\nXXV1NdnZ2axevZpVq1a1GnfAgAGcOXPGm03vMCq0RURERBopLS21FnQqKCggISGBgIAAIiIiGDVq\nVJNtk5KSALDb7W5FeHPCw8O5du2a5xvtA43zcuLECaZOnUpISAgADz/8sLWd3W4HYOTIkZSXl1NW\nVtZi3MDAQGw2230t697ZqdAWERERaaRr1644nc773j8wMJD6+noA6uvrqa2ttb6rqakhODi43W3s\nCPealy5durj93Dgn0JCHxpxOp9/mpSUqtEVEREQaCQsLw+VyUVNTw4gRIzh06BD19fVcv36dU6dO\nNdn24MGDAOTm5lr3Yvfp04eioiIAjh492qTQvnDhAgMGDPBRTzyrcV7GjBnD3r17qaqqAuDGjRvW\ndrcfbDx9+jShoaGEhobSp08fzp49C0BRUZF1fzY0zJT37NkTm83mw974hlaGFBEREbnD2LFjKSgo\nID4+nhMnTpCYmMhjjz3GkCFDrNsnAG7evInD4SAoKIjNmzcDMGPGDDIyMkhOTmbcuHF069bN2j4/\nP5+JEyf6ujseczsv48eP59y5c0ybNg2bzcaECRNYsmQJAMHBwUyePJm6ujrrvvX4+Hiys7Ox2+0M\nGzaMxx9/3Irp7zlpiVaGFBEREblDUVERv/71r/npT39KRUUF3bt3p7S0lOnTp7Nr1y4iIiKIjo7m\nD3/4A+Hh4fccd/bs2fz85z8nLCzMi633nsZ5aU56ejrLly8nMjLynmMuWrSIpUuX0q9fP081s9PQ\njLaIiIjIHYYOHcqoUaNwuVwsXLiQsrIyamtrycjIICIi4r5ilpSUMG/ePL8tsqFpXjzxLm2n00ls\nbOwDWWSDZrRFRERERLxCD0OKiIiIiHiBCm0RERERES9QoS0iIiIi4gUqtEVEREREvECFtoiIiIiI\nF/wfAOvqbvm2/GkAAAAASUVORK5CYII=\n", | |
| "text/plain": [ | |
| "<matplotlib.figure.Figure at 0x7f3dec478208>" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "objects = ('np one img', 'tf one img\\n(gpu)', 'tf one img\\n(cpu)', 'np batch', 'tf batch\\n(gpu)', \n", | |
| " 'tf batch\\n(cpu)', 'np batch\\n+conv', 'tf batch\\n+conv\\n(gpu)', 'tf batch\\n+conv\\n(cpu)')\n", | |
| "y_pos = np.arange(len(objects))\n", | |
| "performance = [large_np.average, large_tf.average, large_tf_cpu.average, \n", | |
| " large_np_batch.average, large_tf_batch.average, large_tf_batch_cpu.average,\n", | |
| " large_np_conv.average, large_tf_conv.average, large_tf_conv_cpu.average]\n", | |
| "performance = [i*1000 for i in performance]\n", | |
| "fig, ax = plt.subplots(1, figsize=(12,12))\n", | |
| "ax.bar(y_pos, performance, align='center', alpha=0.5, color=['red', 'blue', 'green'])\n", | |
| "plt.xticks(y_pos, objects)\n", | |
| "plt.ylabel('Time (ms)')\n", | |
| "plt.title('Times to perform different DTCWT operations on large images')\n", | |
| "plt.show()" | |
| ] | |
| } | |
| ], | |
| "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.5.2" | |
| }, | |
| "toc": { | |
| "colors": { | |
| "hover_highlight": "#DAA520", | |
| "navigate_num": "#000000", | |
| "navigate_text": "#333333", | |
| "running_highlight": "#FF0000", | |
| "selected_highlight": "#FFD700", | |
| "sidebar_border": "#EEEEEE", | |
| "wrapper_background": "#FFFFFF" | |
| }, | |
| "moveMenuLeft": true, | |
| "nav_menu": { | |
| "height": "12px", | |
| "width": "252px" | |
| }, | |
| "navigate_menu": true, | |
| "number_sections": true, | |
| "sideBar": true, | |
| "threshold": 4, | |
| "toc_cell": false, | |
| "toc_section_display": "block", | |
| "toc_window_display": true, | |
| "widenNotebook": false | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 2 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment