{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Wed Jul  1 11:16:12 2020       \n",
      "+-----------------------------------------------------------------------------+\n",
      "| NVIDIA-SMI 440.82       Driver Version: 440.82       CUDA Version: 10.2     |\n",
      "|-------------------------------+----------------------+----------------------+\n",
      "| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |\n",
      "| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |\n",
      "|===============================+======================+======================|\n",
      "|   0  GeForce GTX 106...  Off  | 00000000:01:00.0  On |                  N/A |\n",
      "|  0%   49C    P2    26W / 120W |   2808MiB /  3016MiB |      2%      Default |\n",
      "+-------------------------------+----------------------+----------------------+\n",
      "                                                                               \n",
      "+-----------------------------------------------------------------------------+\n",
      "| Processes:                                                       GPU Memory |\n",
      "|  GPU       PID   Type   Process name                             Usage      |\n",
      "|=============================================================================|\n",
      "|    0      1972      G   /usr/libexec/Xorg                             59MiB |\n",
      "|    0      2361      G   /usr/libexec/Xorg                            280MiB |\n",
      "|    0      2485      G   /usr/bin/gnome-shell                         231MiB |\n",
      "|    0      3214      G   ...uest-channel-token=15065411588967843042    23MiB |\n",
      "|    0      4090      G   /usr/lib64/firefox/firefox                    12MiB |\n",
      "|    0      4151      G   /usr/lib64/firefox/firefox                     2MiB |\n",
      "|    0      4194      G   /usr/lib64/firefox/firefox                     2MiB |\n",
      "|    0      4917      G   /usr/lib64/firefox/firefox                     2MiB |\n",
      "|    0      5777      G   /usr/lib64/firefox/firefox                     2MiB |\n",
      "|    0     33033      G   /usr/lib64/firefox/firefox                     4MiB |\n",
      "|    0     37575      G   /usr/lib64/firefox/firefox                   167MiB |\n",
      "|    0     37626      G   /usr/lib64/firefox/firefox                     2MiB |\n",
      "|    0     50906      G   ...quest-channel-token=3573384613177380021   121MiB |\n",
      "|    0     90844      C   /home/jeff/Documents/python/ml/bin/python   1881MiB |\n",
      "+-----------------------------------------------------------------------------+\n"
     ]
    }
   ],
   "source": [
    "!nvidia-smi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "\n",
    "print(torch.cuda.is_available())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time # times in seconds\n",
    "def time_torch(size):\n",
    "    x = torch.rand(size, size, device=torch.device(\"cuda\"))\n",
    "    start = time.time()\n",
    "    x.sin_()\n",
    "    end = time.time()\n",
    "    return(end - start)\n",
    "\n",
    "def time_cpu(size):\n",
    "    x = torch.rand(size, size, device=torch.device(\"cpu\"))\n",
    "    start = time.time()\n",
    "    x.sin_()\n",
    "    end = time.time()\n",
    "    return(end - start)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "([0.00028634071350097656, 1.049041748046875e-05, 4.291534423828125e-06, 4.0531158447265625e-06], [3.9577484130859375e-05, 1.0728836059570312e-05, 1.0013580322265625e-05, 1.0013580322265625e-05])\n"
     ]
    }
   ],
   "source": [
    "def get_cuda_cpu_times(sizes):\n",
    "    cpuTimes = []\n",
    "    cudaTimes = []\n",
    "\n",
    "    for s in sizes:\n",
    "        cpuTimes += [time_cpu(s)]\n",
    "        cudaTimes += [time_torch(s)]\n",
    "    return cpuTimes, cudaTimes\n",
    "\n",
    "print(get_cuda_cpu_times(range(2, 10, 2)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "def plot_cuda_vs_cpu(cpuTimes, cudaTimes, sizes, xLab=\"Matrix Width\"):\n",
    "    plt.title(\"CUDA vs CPU\")\n",
    "    cpu_plot = plt.plot(sizes, cpuTimes, label=\"CPU\")\n",
    "    cuda_plot = plt.plot(sizes, cudaTimes, label=\"CUDA\")\n",
    "    plt.legend(bbox_to_anchor=(0.8, 0.98), loc='upper left', borderaxespad=0.)\n",
    "    # plt.legend(handles=[cpu_plot, cuda_plot])\n",
    "    plt.xlabel(xLab)\n",
    "    plt.ylabel('Execution Time (Seconds)')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 20820 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "sizes = range(1, 50, 1)\n",
    "cpu_t, cuda_t = get_cuda_cpu_times(sizes)\n",
    "plot_cuda_vs_cpu(cpu_t, cuda_t, sizes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 22388 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "sizes = range(1, 5000, 100)\n",
    "cpu_t, cuda_t = get_cuda_cpu_times(sizes)\n",
    "plot_cuda_vs_cpu(cpu_t, cuda_t, sizes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 22880 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# cpu_plot = plt.plot(sizes, cpuTimes, label=\"CPU\")\n",
    "cuda_plot = plt.plot(sizes, cuda_t, label=\"CUDA\")\n",
    "plt.legend(bbox_to_anchor=(0.8, 0.98), loc='upper left', borderaxespad=0.)\n",
    "# plt.legend(handles=[cpu_plot, cuda_plot])\n",
    "plt.xlabel('Matrix Size')\n",
    "plt.ylabel('Execution Time (Seconds)')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.00036406517028808594"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import time # times in seconds\n",
    "def time_torch_copy(size):\n",
    "    x = torch.rand(size, size, device=torch.device(\"cpu\"))\n",
    "    start = time.time()\n",
    "    x = x.cuda()\n",
    "    x.sin_()\n",
    "    end = time.time()\n",
    "    return(end - start)\n",
    "time_torch_copy(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 25896 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def get_cuda_cpu_times_with_copy(sizes):\n",
    "    cpuTimes = []\n",
    "    cudaTimes = []\n",
    "    for s in sizes:\n",
    "        cpuTimes += [time_cpu(s)]\n",
    "        cudaTimes += [time_torch_copy(s)]\n",
    "    return cpuTimes, cudaTimes\n",
    "\n",
    "sizes = range(1, 5000, 100)\n",
    "cpu_t, cuda_t = get_cuda_cpu_times_with_copy(sizes)\n",
    "plot_cuda_vs_cpu(cpu_t, cuda_t, sizes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 21696 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import time # times in seconds\n",
    "def time_torch_copy_and_back(size):\n",
    "    x = torch.rand(size, size, device=torch.device(\"cpu\"))\n",
    "    start = time.time()\n",
    "    x = x.cuda()\n",
    "    x.sin_()\n",
    "    x = x.cpu()\n",
    "    end = time.time()\n",
    "    return(end - start)\n",
    "time_torch_copy(2)\n",
    "\n",
    "def get_cuda_cpu_times_with_copy(sizes):\n",
    "    cpuTimes = []\n",
    "    cudaTimes = []\n",
    "    for s in sizes:\n",
    "        cpuTimes += [time_cpu(s)]\n",
    "        cudaTimes += [time_torch_copy_and_back(s)]\n",
    "    return cpuTimes, cudaTimes\n",
    "\n",
    "sizes = range(1, 5000, 100)\n",
    "cpu_t, cuda_t = get_cuda_cpu_times_with_copy(sizes)\n",
    "plot_cuda_vs_cpu(cpu_t, cuda_t, sizes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [],
   "source": [
    "def time_torch_operation_repetition(size, iterations):\n",
    "    x = torch.rand(size, size, device=torch.device(\"cpu\"))\n",
    "    start = time.time()\n",
    "    x = x.cuda()\n",
    "    for _ in range(0, iterations):  \n",
    "        x.sin()\n",
    "    end = time.time()\n",
    "    return(end - start)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "def time_cpu_operation_repetition(size, iterations):\n",
    "    x = torch.rand(size, size, device=torch.device(\"cpu\"))\n",
    "    start = time.time()\n",
    "    for _ in range(0, iterations):  \n",
    "        x.sin()\n",
    "    end = time.time()\n",
    "    return(end - start)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_cuda_cpu_times_with_iterations(iterations):\n",
    "    cpuTimes = []\n",
    "    cudaTimes = []\n",
    "    for i in iterations:\n",
    "        cpuTimes += [time_cpu_operation_repetition(300, i)]\n",
    "        cudaTimes += [time_torch_operation_repetition(300, i)]\n",
    "    return cpuTimes, cudaTimes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 24820 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "iterations = range(1, 500, 5)\n",
    "cpu_t, cuda_t = get_cuda_cpu_times_with_iterations(iterations)\n",
    "plot_cuda_vs_cpu(cpu_t, cuda_t, iterations, xLab=\"Number of Operations\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "ml",
   "language": "python",
   "name": "ml"
  },
  "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.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
