Skip to content

Instantly share code, notes, and snippets.

@anyuzx
Last active October 7, 2019 15:35
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 anyuzx/69b1c1f6671133a6ba8feed3cc2813cf to your computer and use it in GitHub Desktop.
Save anyuzx/69b1c1f6671133a6ba8feed3cc2813cf to your computer and use it in GitHub Desktop.
pdist_benchmark_pure_python
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"kernelspec": {
"display_name": "Python3 (scienv)",
"language": "python",
"name": "scienv"
},
"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.3"
},
"colab": {
"name": "pdist_benchmark_pure_python",
"provenance": [],
"include_colab_link": true
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/anyuzx/69b1c1f6671133a6ba8feed3cc2813cf/pdist_benchmark_pure_python.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"metadata": {
"id": "yy6GG5Wm26F_",
"colab_type": "code",
"colab": {}
},
"source": [
"import itertools\n",
"import numpy as np\n",
"import math\n",
"\n",
"import matplotlib\n",
"import matplotlib.pyplot as plt"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "E4Z78Bl_26GL",
"colab_type": "text"
},
"source": [
"<div class=\"alert alert-info\">\n",
" Sample of code shown in the <a href=\"https://www.guangshi.io/posts/python-optimization-using-different-methods/\">blog post</a>\n",
" </div>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "BvnBg-FV26GM",
"colab_type": "text"
},
"source": [
"### Python code to compute pair-wise distances in a periodic boundary condition\n",
"\n",
"In this notebook, several different implementations are provided to compute the pair-wise distances in a periodic boundary condition. The performances are benchmarked to compare the speeed of different implementation. For simplicity, the simulation box is assumed to be a cubic box whose lower left forward corner is at origin. Such set up would simplify the computation of distances.\n",
"\n",
"**Algorithm**: https://en.wikipedia.org/wiki/Periodic_boundary_conditions\n",
"\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wxg0erSG26GN",
"colab_type": "text"
},
"source": [
"#### Pure Python Way\n",
"\n",
"Each particle has three coordinates, $x$, $y$ and $z$. The positions of all particles are stored in a python list `[[x1,y1,z1],[x2,y2,z2],...,[xN,yN,zN]]` where `xi` is the cooridnates for particle $i$. The length of box edge is `l`."
]
},
{
"cell_type": "code",
"metadata": {
"id": "jhfdkNkN26GO",
"colab_type": "code",
"colab": {}
},
"source": [
"# First we need to define a function to compute distane between two points\n",
"def distance(p1, p2, l):\n",
" \"\"\"\n",
" Computes the distance between two points, p1 and p2.\n",
"\n",
" p1/p2:python list with form [x1, y1, z1] and [x2, y2, z2] representing the cooridnate at that dimension\n",
" l: the length of edge of box (cubic/square box)\n",
" return: a number (distance)\n",
" \"\"\"\n",
" dim = len(p1)\n",
" D = [p1[i] - p2[i] for i in range(dim)]\n",
" distance = math.sqrt(sum(map(lambda x: (x - round(x / l) * l) ** 2.0, D)))\n",
" return distance\n",
"\n",
"# Now we define function to iterate over all possible pairs of points from a list of points\n",
"def pdist(positions, l):\n",
" \"\"\"\n",
" Compute the pair-wise distances between every possible pair of particles.\n",
"\n",
" positions: a python list in which each element is a a list of cooridnates\n",
" l: the length of edge of box (cubic/square box)\n",
" return: a condensed 1D list\n",
" \"\"\"\n",
" n = len(positions)\n",
" pdistances = []\n",
" for i in range(n-1):\n",
" for j in range(i+1, n):\n",
" pdistances.append(distance(positions[i], positions[j], l))\n",
" return pdistances"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "_PAA3bo926GR",
"colab_type": "code",
"colab": {}
},
"source": [
"# version of python code use itertools.combination\n",
"def pdist_v2(positions, l):\n",
" iterator = itertools.combinations(positions, r=2)\n",
" return [math.sqrt(sum(map(lambda x, y: (x - y - round((x - y) / l) * l) ** 2.0, *item))) for item in iterator]"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "ymV3FS3J26GU",
"colab_type": "text"
},
"source": [
"##### Benchmarks"
]
},
{
"cell_type": "code",
"metadata": {
"id": "cQH82KkM26GU",
"colab_type": "code",
"outputId": "64ad82aa-1880-4a0b-faee-7fe78be63727",
"colab": {}
},
"source": [
"performance = []\n",
"performance_v2 = []\n",
"\n",
"for n in np.linspace(10, 1000, 10, dtype=np.int):\n",
" positions = np.random.rand(n,3).tolist()\n",
" result = %timeit -o pdist(positions, 1.0)\n",
" result_v2 = %timeit -o pdist_v2(positions, 1.0)\n",
" performance.append([n, result.average])\n",
" performance_v2.append([n, result_v2.average])"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"125 µs ± 16.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n",
"94.2 µs ± 9.51 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n",
"21.3 ms ± 2.68 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
"15 ms ± 2.29 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
"73.5 ms ± 8.51 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"49.4 ms ± 1.84 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"150 ms ± 3.27 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"105 ms ± 3.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"262 ms ± 7.39 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"180 ms ± 2.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
"423 ms ± 31 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"290 ms ± 18.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"595 ms ± 24.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"448 ms ± 41.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"806 ms ± 33.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"553 ms ± 17 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"1.05 s ± 37 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"757 ms ± 31.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"1.55 s ± 209 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
"919 ms ± 41 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "n_OmKFXm26GY",
"colab_type": "code",
"outputId": "0be82770-fff1-4e51-b496-08835239c5c9",
"colab": {}
},
"source": [
"performance = np.asarray(performance)\n",
"performance_v2 = np.asarray(performance_v2)\n",
"\n",
"\n",
"fig, ax = plt.subplots()\n",
"ax.plot(performance[:,0], performance[:,1], label='pdist', marker='o')\n",
"ax.plot(performance_v2[:,0], performance_v2[:,1], label='pdist_v2', marker='o')\n",
"ax.set_xlabel(r'$N$')\n",
"ax.set_ylabel('Time Spent (seconds)')\n",
"ax.legend(loc='upper left')\n",
"plt.show()"
],
"execution_count": 0,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "gLKpV-WX26Gb",
"colab_type": "code",
"colab": {}
},
"source": [
""
],
"execution_count": 0,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment