{ "cells": [ { "cell_type": "markdown", "id": "cloudy-garage", "metadata": { "tags": [] }, "source": [ "# Comparing threading and multiprocessing" ] }, { "cell_type": "code", "execution_count": 1, "id": "radical-fisher", "metadata": { "tags": [] }, "outputs": [], "source": [ "import time\n", "\n", "import multiprocessing as mp\n", "from multiprocessing import Pool as ProcessPool\n", "from multiprocessing.pool import ThreadPool\n", "\n", "import pandas as pd\n", "\n", "import seaborn as sns\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 2, "id": "crazy-organic", "metadata": { "tags": [] }, "outputs": [], "source": [ "sns.set_context('talk')" ] }, { "cell_type": "markdown", "id": "lucky-sudan", "metadata": { "tags": [] }, "source": [ "## Introduction\n", "\n", "There are various choices when trying to run code in parallel.\n", "\n", "The `threading` module will run all threads on the same CPU core which requires less overhead and allows for more efficient sharing of memory. However, it is not truly parallel and executes the threads when others are idling.\n", "\n", "The `multiprocessing` module runs the processes on multiple CPU cores and can thus execute code at the same time." ] }, { "cell_type": "markdown", "id": "north-final", "metadata": { "tags": [] }, "source": [ "## Preparations" ] }, { "cell_type": "markdown", "id": "considered-length", "metadata": { "tags": [] }, "source": [ "To investigate the differences between threading and multiprocessing,\n", "we will simulate work for each data point and measure when it was executed.\n", "\n", "Due to some [design choices](https://bugs.python.org/issue25053), we have to import the worker function from a separate module for the `ProcessPool` to work." ] }, { "cell_type": "code", "execution_count": 3, "id": "ruled-exclusive", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting worker.py\n" ] } ], "source": [ "%%writefile worker.py\n", "\n", "import time\n", "\n", "\n", "def worker(data):\n", " tmp = []\n", " for i in data:\n", " # simulate CPU load\n", " for _ in range(1_000_000):\n", " pass\n", "\n", " # store execution time\n", " tmp.append(time.time())\n", " return tmp " ] }, { "cell_type": "code", "execution_count": 4, "id": "immediate-white", "metadata": { "tags": [] }, "outputs": [], "source": [ "from worker import worker" ] }, { "cell_type": "code", "execution_count": 5, "id": "cutting-freeware", "metadata": { "tags": [] }, "outputs": [], "source": [ "data = list(range(20))\n", "num = mp.cpu_count()" ] }, { "cell_type": "markdown", "id": "horizontal-arnold", "metadata": { "tags": [] }, "source": [ "## Computations" ] }, { "cell_type": "markdown", "id": "valid-header", "metadata": { "tags": [] }, "source": [ "We run the `worker` function on the dataset for each executor in both the process and thread pool." ] }, { "cell_type": "code", "execution_count": 6, "id": "laden-albania", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 3.79 s, sys: 131 ms, total: 3.92 s\n", "Wall time: 3.86 s\n" ] } ], "source": [ "%%time\n", "with ThreadPool(num) as p:\n", " thread_result = p.map(worker, [data] * num)" ] }, { "cell_type": "code", "execution_count": 7, "id": "committed-volunteer", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 26 ms, sys: 56.7 ms, total: 82.7 ms\n", "Wall time: 1.4 s\n" ] } ], "source": [ "%%time\n", "with ProcessPool(num) as p:\n", " process_result = p.map(worker, [data] * num)" ] }, { "cell_type": "markdown", "id": "convertible-slovakia", "metadata": { "tags": [] }, "source": [ "Next, we store the result in a dataframe." ] }, { "cell_type": "code", "execution_count": 8, "id": "brilliant-concord", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
variablevaluetype
0job 00.105189thread
1job 00.316431thread
2job 00.592710thread
3job 00.704985thread
4job 00.822085thread
\n", "
" ], "text/plain": [ " variable value type\n", "0 job 0 0.105189 thread\n", "1 job 0 0.316431 thread\n", "2 job 0 0.592710 thread\n", "3 job 0 0.704985 thread\n", "4 job 0 0.822085 thread" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_thread = pd.melt(\n", " pd.DataFrame(thread_result, index=[f'job {i:2}' for i in range(num)]).T\n", ")\n", "df_thread['type'] = 'thread'\n", "\n", "df_process = pd.melt(\n", " pd.DataFrame(process_result, index=[f'job {i:2}' for i in range(num)]).T\n", ")\n", "df_process['type'] = 'process'\n", "\n", "df = pd.concat([df_thread, df_process], ignore_index=True)\n", "df['value'] = df.groupby('type')['value'].apply(lambda x: x - x.min()) # normalize time\n", "df.head()" ] }, { "cell_type": "markdown", "id": "internal-williams", "metadata": { "tags": [] }, "source": [ "## Investigation" ] }, { "cell_type": "markdown", "id": "assigned-opportunity", "metadata": { "tags": [] }, "source": [ "There are two main observations:\n", "\n", "* `multiprocessing` execution takes less total runtime than `threading`\n", "\n", "* `multiprocessing` timestamps are in parallel, while `threading` timestamps are serial" ] }, { "cell_type": "code", "execution_count": 9, "id": "basic-source", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "g = sns.FacetGrid(df, row='type', aspect=2)\n", "g.map_dataframe(sns.scatterplot, x='value', y='variable')\n", "g.set_axis_labels('Time [s]', 'Pool')" ] }, { "cell_type": "markdown", "id": "worst-emphasis", "metadata": { "tags": [] }, "source": [ "The decision whether to use threading or multiprocessing depends on the use case.\n", "\n", "As a general rule of thumb, one should use threading if the problem is IO bound and multiprocessing if it is CPU bound." ] } ], "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.8.6" } }, "nbformat": 4, "nbformat_minor": 5 }