Skip to content

Instantly share code, notes, and snippets.

@minrk
Last active December 16, 2015 21:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save minrk/5500077 to your computer and use it in GitHub Desktop.
Save minrk/5500077 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "CPU Affinity"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Setting CPU Affinity with IPython.parallel and psutil"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[CPU Affinity](http://en.wikipedia.org/wiki/CPU_affinity) lets you pin processes to particular processors on your machine.\n",
"The Python package [psutil](https://code.google.com/p/psutil/) lets you view and edit the CPU affinity of any process."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import os\n",
"import psutil\n",
"p = psutil.Process(os.getpid())\n",
"p.get_cpu_affinity()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 4,
"text": [
"[0, 1, 2, 3]"
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Setting CPU affinity can be [a problem](http://stackoverflow.com/questions/16323743/ipython-parallel-does-not-use-multicore) if you aren't aware that it is happening.\n",
"The most common way for CPU affinity to be set without the user being aware is importing numpy linked against particular BLAS libraries.\n",
"\n",
"The most common symptom of this will be that all of your IPython engines will use just one core.\n",
"\n",
"Let's check if this happens here:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import numpy\n",
"p.get_cpu_affinity()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 5,
"text": [
"[0, 1, 2, 3]"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, so we are fine. There are a few logical cases where we want to set the CPU affinity of our engines.\n",
"\n",
"1. We want to pin each engine to a particular CPU core.\n",
"2. Something else set the affinity to something we don't want, and we want to put it back to the default.\n",
"3. We want to limit all of our engines to a few CPUs"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Pinning each engine to a core"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython import parallel"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"rc = parallel.Client()\n",
"dview = rc[:]\n",
"rc.ids"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 11,
"text": [
"[0, 1, 2, 3]"
]
}
],
"prompt_number": 11
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This assumes that you already only have one engine per core. In this case, I have four."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"dview.scatter(\"cpu\", range(len(dview)), flatten=True)\n",
"%px print cpu"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[stdout:0] 0\n",
"[stdout:1] 1\n",
"[stdout:2] 2\n",
"[stdout:3] 3\n"
]
}
],
"prompt_number": 14
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can set the affinity of each engine to a single CPU core,\n",
"so the engines won't be fighting over CPU resources."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%px\n",
"import os\n",
"import psutil\n",
"\n",
"p = psutil.Process(os.getpid())\n",
"p.set_cpu_affinity([cpu])\n",
"print p.get_cpu_affinity()\n"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[stdout:0] [0]\n",
"[stdout:1] [1]\n",
"[stdout:2] [2]\n",
"[stdout:3] [3]\n"
]
}
],
"prompt_number": 18
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Unpinning engines"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A simpler case is just restoring CPU affinity after some library may have set it inappropriately.\n",
"\n",
"We use the `multiprocessing.cpu_count` to get the number of CPUs."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%px\n",
"import os\n",
"import psutil\n",
"from multiprocessing import cpu_count\n",
"\n",
"p = psutil.Process(os.getpid())\n",
"p.set_cpu_affinity(range(cpu_count()))\n",
"print p.get_cpu_affinity()\n"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[stdout:0] [0, 1, 2, 3]\n",
"[stdout:1] [0, 1, 2, 3]\n",
"[stdout:2] [0, 1, 2, 3]\n",
"[stdout:3] [0, 1, 2, 3]\n"
]
}
],
"prompt_number": 23
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment