325 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			325 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
{
 | 
						|
 "cells": [
 | 
						|
  {
 | 
						|
   "cell_type": "markdown",
 | 
						|
   "metadata": {
 | 
						|
    "collapsed": true
 | 
						|
   },
 | 
						|
   "source": [
 | 
						|
    "# Description of Functionality"
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "markdown",
 | 
						|
   "metadata": {},
 | 
						|
   "source": [
 | 
						|
    "# Algorithm\n",
 | 
						|
    "\n",
 | 
						|
    "## Load settings from JSON file\n",
 | 
						|
    "\n"
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "code",
 | 
						|
   "execution_count": null,
 | 
						|
   "metadata": {},
 | 
						|
   "outputs": [],
 | 
						|
   "source": [
 | 
						|
    "import os\n",
 | 
						|
    "from sys import argv\n",
 | 
						|
    "rootdir = argv[1]\n",
 | 
						|
    "\n",
 | 
						|
    "#############################\n",
 | 
						|
    "#      FOR NOTEBOOK USE     #\n",
 | 
						|
    "#     SET DIRECTORY HERE    #\n",
 | 
						|
    "#                           #\n",
 | 
						|
    "#rootdir = \"\"\n",
 | 
						|
    "#                           #\n",
 | 
						|
    "#############################\n",
 | 
						|
    "\n",
 | 
						|
    "print(\"Using root directory: {}\".format(rootdir))\n",
 | 
						|
    "\n",
 | 
						|
    "# Get the subdirs with the different tests\n",
 | 
						|
    "subdirs = sorted([ name for name in os.listdir('{}'.format(rootdir)) if os.path.isdir(os.path.join('{}'.format(rootdir), name)) ])\n",
 | 
						|
    "print(\"Available subdirs: {}\".format(subdirs))\n",
 | 
						|
    "\n",
 | 
						|
    "# Get subsubdirs with the several size shifts\n",
 | 
						|
    "subsubdirs = []\n",
 | 
						|
    "for subdir in subdirs:\n",
 | 
						|
    "    subsubdirs.append(sorted([ name for name in os.listdir('{}/{}'.format(rootdir, subdir)) if os.path.isdir(os.path.join('{}/{}'.format(rootdir, subdir), name)) ]))\n",
 | 
						|
    "\n",
 | 
						|
    "print(\"Loaded all subsubdirs!\")"
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "code",
 | 
						|
   "execution_count": null,
 | 
						|
   "metadata": {},
 | 
						|
   "outputs": [],
 | 
						|
   "source": [
 | 
						|
    "import json\n",
 | 
						|
    "from sys import exit\n",
 | 
						|
    "\n",
 | 
						|
    "try:\n",
 | 
						|
    "    with open(\"{}/settings.json\".format(rootdir)) as json_file:\n",
 | 
						|
    "        settings = json.load(json_file)\n",
 | 
						|
    "except:\n",
 | 
						|
    "    print(\"Please define a correct JSON file!\")\n",
 | 
						|
    "    exit()\n",
 | 
						|
    "\n",
 | 
						|
    "print(\"Succesfully loaded JSON file\")"
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "markdown",
 | 
						|
   "metadata": {},
 | 
						|
   "source": [
 | 
						|
    "## Import\n",
 | 
						|
    "First, import the numpy library, initialize the arrays, and finally load the csv files. \n",
 | 
						|
    "\n",
 | 
						|
    "Because of the way the C script dumps the variables, the last character of the csv-file will be a comma and thus the last value of the `*_times` arrays will be `NaN`. Hence, the last value has to be eliminated."
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "code",
 | 
						|
   "execution_count": null,
 | 
						|
   "metadata": {},
 | 
						|
   "outputs": [],
 | 
						|
   "source": [
 | 
						|
    "import numpy as np\n",
 | 
						|
    "\n",
 | 
						|
    "# Initialize arrays\n",
 | 
						|
    "enq_send = []\n",
 | 
						|
    "recv = []\n",
 | 
						|
    "\n",
 | 
						|
    "number_of_datapoints = 0\n",
 | 
						|
    "\n",
 | 
						|
    "# Load all data and remove the last comma.\n",
 | 
						|
    "# This for loop distinguish between tests which measure the enqueue time and tests which\n",
 | 
						|
    "# measure the actual send time.\n",
 | 
						|
    "for i, subdir in enumerate(subdirs):\n",
 | 
						|
    "    enq_send.append([None] * len(subsubdirs[i]))\n",
 | 
						|
    "    recv.append([None] * len(subsubdirs[i]))\n",
 | 
						|
    "    for j, subsubdir in enumerate(subsubdirs[i]):\n",
 | 
						|
    "        enq_send[i][j] = np.genfromtxt('{}/{}/{}/enq_send_times.csv'.format(rootdir, subdir, subsubdir), delimiter=',')\n",
 | 
						|
    "        recv[i][j] = np.genfromtxt('{}/{}/{}/recv_times.csv'.format(rootdir, subdir, subsubdir), delimiter=',')\n",
 | 
						|
    "    \n",
 | 
						|
    "        # Remove last comma\n",
 | 
						|
    "        enq_send[i][j] = np.delete(enq_send[i][j], -1)\n",
 | 
						|
    "        recv[i][j] = np.delete(recv[i][j], -1)\n",
 | 
						|
    "\n",
 | 
						|
    "        #Print number of datapoints\n",
 | 
						|
    "        print('Loaded {} + {} datapoints from {}/{}.'.format(np.size(enq_send[i][j]), np.size(recv[i][j]), subdir, subsubdir))\n"
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "markdown",
 | 
						|
   "metadata": {
 | 
						|
    "collapsed": true
 | 
						|
   },
 | 
						|
   "source": [
 | 
						|
    "## Process data\n",
 | 
						|
    "Now, the data is processed. First, a check for overflows have to be performed. The timestamps are determined with the function `clock_gettime(clockid_t clk_id, const struct timespec *tp)`. Both the `struct tp`, as well as the function are showed below\n",
 | 
						|
    "\n",
 | 
						|
    "```\n",
 | 
						|
    "struct timespec {\n",
 | 
						|
    "  time_t   tv_sec;        /* seconds */\n",
 | 
						|
    "  long     tv_nsec;       /* nanoseconds */\n",
 | 
						|
    "} tp;\n",
 | 
						|
    "\n",
 | 
						|
    "clock_gettime(CLOCK_MONOTONIC, &tp);\n",
 | 
						|
    "```\n",
 | 
						|
    "\n",
 | 
						|
    "The application only sends the `long tv_nsec` value, which goes from 999999999ns to 0ns. Since transmissions cannot take longer than 1 second, this overflow is resolved by adding 1000000000ns to the receive timestamps and the send confirmation timestamps, if they are smaller than the enqueue- or send timestamps.\n",
 | 
						|
    "\n",
 | 
						|
    "Subsequentely, the deltas between the enqueue- or send time and the receive time, and the delta between the enqueue- or send time and the send confirmation time are calculated."
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "code",
 | 
						|
   "execution_count": null,
 | 
						|
   "metadata": {},
 | 
						|
   "outputs": [],
 | 
						|
   "source": [
 | 
						|
    "# Initialize arrays\n",
 | 
						|
    "enq_send_recv_d = []\n",
 | 
						|
    "medians = []\n",
 | 
						|
    "upper_limit = []\n",
 | 
						|
    "lower_limit = []\n",
 | 
						|
    "\n",
 | 
						|
    "# Resolve overflow issues and then calculate deltas\n",
 | 
						|
    "for i in range(0, len(subdirs)):\n",
 | 
						|
    "    medians.append([])\n",
 | 
						|
    "    upper_limit.append([])\n",
 | 
						|
    "    lower_limit.append([])\n",
 | 
						|
    "    for j in range(0, len(subsubdirs[i])):\n",
 | 
						|
    "        recv[i][j][recv[i][j] < enq_send[i][j]] += 1000000000\n",
 | 
						|
    "\n",
 | 
						|
    "        medians[i].append(np.median(recv[i][j] - enq_send[i][j]))\n",
 | 
						|
    "        \n",
 | 
						|
    "        # np.sort(recv[i][j] - enq_send[i][j])[int(np.size(recv[i][j]]) / 2)] would be the approximately the median\n",
 | 
						|
    "        # Calculate upper 10% and lower 10%\n",
 | 
						|
    "        upper_limit[i].append(abs(medians[i][j] - np.sort(recv[i][j] - enq_send[i][j])[int(9 * np.size(recv[i][j]) / 10)]))\n",
 | 
						|
    "        lower_limit[i].append(abs(medians[i][j] - np.sort(recv[i][j] - enq_send[i][j])[int(1 * np.size(recv[i][j]) / 10)]))"
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "markdown",
 | 
						|
   "metadata": {},
 | 
						|
   "source": [
 | 
						|
    "## Plotting\n",
 | 
						|
    "\n",
 | 
						|
    "The data will now be plotted."
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "code",
 | 
						|
   "execution_count": null,
 | 
						|
   "metadata": {},
 | 
						|
   "outputs": [],
 | 
						|
   "source": [
 | 
						|
    "# Define \"find nearest\" function\n",
 | 
						|
    "def find_nearest(array, value):\n",
 | 
						|
    "    array = np.asarray(array)\n",
 | 
						|
    "    idx = (np.abs(array - value)).argmin()\n",
 | 
						|
    "    return array[idx], idx"
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "code",
 | 
						|
   "execution_count": null,
 | 
						|
   "metadata": {
 | 
						|
    "scrolled": false
 | 
						|
   },
 | 
						|
   "outputs": [],
 | 
						|
   "source": [
 | 
						|
    "import matplotlib.pyplot as plt\n",
 | 
						|
    "from matplotlib.font_manager import FontProperties\n",
 | 
						|
    "import os\n",
 | 
						|
    "\n",
 | 
						|
    "#First, delete all old plots and recreate the directory\n",
 | 
						|
    "os.system('rm -rf ./plots')\n",
 | 
						|
    "os.system('mkdir ./plots')\n",
 | 
						|
    "\n",
 | 
						|
    "plots_saved = 0\n",
 | 
						|
    "\n",
 | 
						|
    "#Start adding data\n",
 | 
						|
    "for i in range(0, len(subdirs)):\n",
 | 
						|
    "    y_data = np.array([])\n",
 | 
						|
    "    x_data = np.array([])\n",
 | 
						|
    "\n",
 | 
						|
    "    for j in range(0, len(subsubdirs[i])):\n",
 | 
						|
    "        x_data = np.append(x_data, j)\n",
 | 
						|
    "        y_data = np.append(y_data, medians[i][j])\n",
 | 
						|
    "        \n",
 | 
						|
    "    if i in settings['iter_to_start_new_plot']:\n",
 | 
						|
    "        width = 1.125 * settings['dimensions']['figure'][0] if i == 0 else settings['dimensions']['figure'][0]\n",
 | 
						|
    "        fig = plt.figure(num=None, figsize=(width, settings['dimensions']['figure'][1]), dpi=500, facecolor='w', edgecolor='k')\n",
 | 
						|
    "        \n",
 | 
						|
    "        # Add plot and set title\n",
 | 
						|
    "        ax = fig.add_subplot(111)\n",
 | 
						|
    "\n",
 | 
						|
    "    ax.errorbar(x_data, medians[i], yerr = [lower_limit[i], upper_limit[i]],\n",
 | 
						|
    "                capsize = 3.7, elinewidth = 1, markeredgewidth = 1, zorder = 2+i,\n",
 | 
						|
    "                color = settings['colors'][(i + settings['skip_label'][i]) % len(settings['colors'])],\n",
 | 
						|
    "                marker = settings['markers'][(i + settings['skip_label'][i]) % len(settings['markers'])],\n",
 | 
						|
    "                label = settings['labels'][(i + settings['skip_label'][i]) % len(settings['labels'])])\n",
 | 
						|
    "\n",
 | 
						|
    "    if i in settings['iter_to_end_plot']:\n",
 | 
						|
    "        # Set grid\n",
 | 
						|
    "        ax.set_axisbelow(True)\n",
 | 
						|
    "        ax.grid(True, linestyle='--')\n",
 | 
						|
    "\n",
 | 
						|
    "        # Generate plot\n",
 | 
						|
    "       \n",
 | 
						|
    "        #Labels\n",
 | 
						|
    "        font_text = FontProperties()\n",
 | 
						|
    "        font_text.set_size(9.5)\n",
 | 
						|
    "        font_text.set_family('monospace')\n",
 | 
						|
    "\n",
 | 
						|
    "        # Set axis\n",
 | 
						|
    "        plt.xlim([0, settings['limits'][0]])\n",
 | 
						|
    "        plt.ylim([0, settings['limits'][1]])\n",
 | 
						|
    "\n",
 | 
						|
    "        # Set ticks\n",
 | 
						|
    "        ticks_unmodified = ticks = np.arange(0, settings['limits'][0] + 1, 1.0)\n",
 | 
						|
    "\n",
 | 
						|
    "        # Explicitly set labels\n",
 | 
						|
    "        labels = []\n",
 | 
						|
    "        for k in range(0,13):\n",
 | 
						|
    "            value = 8 * 2 ** k\n",
 | 
						|
    "            labels.append(str(value))\n",
 | 
						|
    "\n",
 | 
						|
    "        # Set xticks\n",
 | 
						|
    "        plt.xticks(ticks, labels, fontsize=10.5, family='monospace', rotation=30, horizontalalignment='right', rotation_mode=\"anchor\")\n",
 | 
						|
    "    \n",
 | 
						|
    "        if i == settings['iter_to_end_plot'][0]:\n",
 | 
						|
    "            ax.set_ylabel('$\\\\tilde{t}_{lat}$ [ns]', fontsize=11, family='monospace', labelpad=6)\n",
 | 
						|
    "        else:\n",
 | 
						|
    "            ax.get_yaxis().set_ticklabels([])\n",
 | 
						|
    "\n",
 | 
						|
    "        # Set yticks\n",
 | 
						|
    "        plt.yticks(fontsize=10, family='monospace')\n",
 | 
						|
    "\n",
 | 
						|
    "        ax.set_xlabel('message size [B]', fontsize=10.5, family='monospace', labelpad=4)\n",
 | 
						|
    "\n",
 | 
						|
    "        ax.yaxis.grid(True, linestyle='-', which='major', color='black', alpha=0.8)\n",
 | 
						|
    "        ax.yaxis.grid(True, linestyle='--', which='minor', color='lightgrey', alpha=0.3)\n",
 | 
						|
    "\n",
 | 
						|
    "        plt.minorticks_on()\n",
 | 
						|
    "        plt.tight_layout()\n",
 | 
						|
    "\n",
 | 
						|
    "        # Save plot\n",
 | 
						|
    "        fig.savefig('{}/plot_{}.pdf'.format(rootdir, plots_saved), dpi=600, format='pdf')\n",
 | 
						|
    "        plots_saved += 1\n",
 | 
						|
    "\n",
 | 
						|
    "        if i == settings['iter_to_end_plot'][0]:\n",
 | 
						|
    "            # Create and save legend\n",
 | 
						|
    "            import pylab\n",
 | 
						|
    "\n",
 | 
						|
    "            # create a second figure for the legend\n",
 | 
						|
    "            figLegend = pylab.figure(figsize = settings['dimensions']['legend'])\n",
 | 
						|
    "\n",
 | 
						|
    "            # produce a legend for the objects in the other figure\n",
 | 
						|
    "            pylab.figlegend(*ax.get_legend_handles_labels(), loc = 'upper left',\n",
 | 
						|
    "                            prop={'family':'monospace', 'size':'8'}, ncol=2)\n",
 | 
						|
    "            figLegend.savefig(\"{}/legend.pdf\".format(rootdir), format='pdf')\n",
 | 
						|
    "            "
 | 
						|
   ]
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "raw",
 | 
						|
   "metadata": {},
 | 
						|
   "source": []
 | 
						|
  },
 | 
						|
  {
 | 
						|
   "cell_type": "code",
 | 
						|
   "execution_count": null,
 | 
						|
   "metadata": {},
 | 
						|
   "outputs": [],
 | 
						|
   "source": []
 | 
						|
  }
 | 
						|
 ],
 | 
						|
 "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.7.0"
 | 
						|
  }
 | 
						|
 },
 | 
						|
 "nbformat": 4,
 | 
						|
 "nbformat_minor": 2
 | 
						|
}
 |