Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save perrygeo/2f1b52149f285c00c500 to your computer and use it in GitHub Desktop.

Select an option

Save perrygeo/2f1b52149f285c00c500 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Parallelizing numpy array loops with Cython and MPI\n",
"\n",
"In this notebook, I walk through a basic example of a `numpy` array processing function in Python and a few tricks to speed up the computationally intensive loops in parallel using Cython's OpenMPI support. An important advantage to this technique is that the parallelism has no impact on the function signature and very little impact on the readability of the algorithm itself (as compared to other techniques such as multiprocessing, asyncio, native thread pools which force you to interweave your logic with thread/process management code).\n",
"\n",
"## Software\n",
"\n",
"The software I used for this notebook includes:\n",
"\n",
"```\n",
"numpy==1.8.2\n",
"Cython==0.22\n",
"python3.4\n",
"libopenmpi\n",
"```\n",
"\n",
"Unfortunately for OS X users, `clang` doesn't support openmpi yet so, if you want to use this technique you'll need to do it on a Linux box. I'm using Ubuntu 14.04LTS 64 bit in VirtualBox, set up using the following `Vagrantfile`:\n",
"\n",
"```\n",
"Vagrant::Config.run do |config|\n",
" config.vm.box = \"ubuntu/trusty64\"\n",
" config.vm.customize [\"modifyvm\", :id, \"--cpus\", 4]\n",
" config.vm.customize [\"modifyvm\", :id, \"--memory\", 4898]\n",
" config.vm.forward_port 8888, 8888\n",
" config.vm.share_folder \"v-app\", \"/usr/local/src\", \"./\", mount_options: [\"dmode=775,fmode=664\"]\n",
"end\n",
"```\n",
"\n",
"\n",
"## Basic Python Loop\n",
"\n",
"We'll start our function in pure python so we can get a starting benchmark. Let's assume a 2D array of double-precision numbers:\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"indata = np.random.rand(1400,1600)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And we'll also need to create an array to hold the output values (why edit in place instead of returning an array? Later when we start writing functions that compile to C, we don't want to be constructing python objects)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"outdata = np.zeros(shape=indata.shape, dtype='float64') # eventually holds our output"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The processing function itself is not the main focus of this but a few details should be explained. We'll be using a 3x3 moving window to write our own kernel, a common operation in image processing and raster geospatial data analysis. As such we'll need to pad the edges of the input array."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"shape before (1400, 1600)\n",
"shape after (1402, 1602)\n"
]
}
],
"source": [
"from numpy.lib import pad\n",
"print(\"shape before\", indata.shape)\n",
"indata = pad(indata, (1, 1), 'reflect', reflect_type='odd') # allow edge calcs\n",
"print(\"shape after\", indata.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our 2D input array simulates as digital elevation model (DEM), a regular grid of elevation values from which we can derive many useful parameters. Our function will calculate the slope of the landscape at each 3x3 window using the [Zevenbergen-Thorne method](http://solim.geography.wisc.edu/axing/teaching/geog579/lectures/references/ZevenbergenAndThorne_DigitalTerrain_EarthSurfaceProcesses1987.pdf)\n",
"\n",
"<img height=\"20%\" width=\"20%\" src=\"grid.png\">\n",
"<img height=\"33%\" width=\"33%\" src=\"zt.png\">"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" The details of the slope calculation are another topic. For the purposes of this notebook it merely demonstrates a sufficiently cpu-intensive array loop that we can make faster."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import math\n",
"def slope(indata, outdata):\n",
" I = outdata.shape[0]\n",
" J = outdata.shape[1]\n",
" for i in range(I):\n",
" for j in range(J):\n",
" # percent slope using Zevenbergen-Thorne method\n",
" # assume edges added, inarr is offset by one on both axes cmp to outarr\n",
" dzdx = (indata[i+1, j] - indata[i+1, j+2]) / 2 # assume cellsize == one unit, otherwise (2 * cellsize)\n",
" dzdy = (indata[i, j+1] - indata[i+2, j+1]) / 2\n",
" slp = math.sqrt((dzdx * dzdx) + (dzdy * dzdy)) * 100 # percent slope (take math.atan to get angle)\n",
" outdata[i, j] = slp"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pure python benchmark (python is not good at loops)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1 loops, best of 3: 8.87 s per loop\n"
]
}
],
"source": [
"%timeit slope(indata, outdata)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And because `outdata` was altered in place..."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 53.62073889, 37.25761762, 49.22572304, ..., 12.10829958,\n",
" 65.13054666, 65.2663227 ],\n",
" [ 44.01294737, 10.76722869, 23.27473962, ..., 15.8081327 ,\n",
" 21.29115313, 36.22727089],\n",
" [ 61.05151453, 47.88748414, 48.23457609, ..., 25.27902136,\n",
" 27.50940152, 22.99132025],\n",
" ..., \n",
" [ 72.75415496, 7.36009883, 28.899056 , ..., 1.72762554,\n",
" 6.43332869, 39.40443768],\n",
" [ 51.14738132, 28.89177493, 8.43880328, ..., 4.30343362,\n",
" 24.30767745, 31.93830856],\n",
" [ 31.81405773, 45.86410336, 10.4444242 , ..., 27.2235852 ,\n",
" 39.61055991, 49.20948366]])"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"outdata"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"we'll need to reset it"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def reset_outdata():\n",
" outdata = np.zeros(shape=indata.shape, dtype='float64')\n",
"reset_outdata()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Cython\n",
"\n",
"Cython provides a big win here, compiling code that looks almost like the original Python code into a native extension. Python with C speed."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"%load_ext Cython"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<!DOCTYPE html>\n",
"<!-- Generated by Cython 0.22 -->\n",
"<html>\n",
"<head>\n",
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
" <style type=\"text/css\">\n",
" \n",
"body.cython { font-family: courier; font-size: 12; }\n",
"\n",
".cython.tag { }\n",
".cython.line { margin: 0em }\n",
".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 20px; }\n",
"\n",
".cython.code .py_c_api { color: red; }\n",
".cython.code .py_macro_api { color: #FF7000; }\n",
".cython.code .pyx_c_api { color: #FF3000; }\n",
".cython.code .pyx_macro_api { color: #FF7000; }\n",
".cython.code .refnanny { color: #FFA000; }\n",
".cython.code .error_goto { color: #FFA000; }\n",
"\n",
".cython.code .coerce { color: #008000; border: 1px dotted #008000 }\n",
".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
".cython.code .c_attr { color: #0000FF; }\n",
".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
".cython.code .c_call { color: #0000FF; }\n",
"\n",
".cython.score-0 {background-color: #FFFFff;}\n",
".cython.score-1 {background-color: #FFFFe7;}\n",
".cython.score-2 {background-color: #FFFFd4;}\n",
".cython.score-3 {background-color: #FFFFc4;}\n",
".cython.score-4 {background-color: #FFFFb6;}\n",
".cython.score-5 {background-color: #FFFFaa;}\n",
".cython.score-6 {background-color: #FFFF9f;}\n",
".cython.score-7 {background-color: #FFFF96;}\n",
".cython.score-8 {background-color: #FFFF8d;}\n",
".cython.score-9 {background-color: #FFFF86;}\n",
".cython.score-10 {background-color: #FFFF7f;}\n",
".cython.score-11 {background-color: #FFFF79;}\n",
".cython.score-12 {background-color: #FFFF73;}\n",
".cython.score-13 {background-color: #FFFF6e;}\n",
".cython.score-14 {background-color: #FFFF6a;}\n",
".cython.score-15 {background-color: #FFFF66;}\n",
".cython.score-16 {background-color: #FFFF62;}\n",
".cython.score-17 {background-color: #FFFF5e;}\n",
".cython.score-18 {background-color: #FFFF5b;}\n",
".cython.score-19 {background-color: #FFFF57;}\n",
".cython.score-20 {background-color: #FFFF55;}\n",
".cython.score-21 {background-color: #FFFF52;}\n",
".cython.score-22 {background-color: #FFFF4f;}\n",
".cython.score-23 {background-color: #FFFF4d;}\n",
".cython.score-24 {background-color: #FFFF4b;}\n",
".cython.score-25 {background-color: #FFFF48;}\n",
".cython.score-26 {background-color: #FFFF46;}\n",
".cython.score-27 {background-color: #FFFF44;}\n",
".cython.score-28 {background-color: #FFFF43;}\n",
".cython.score-29 {background-color: #FFFF41;}\n",
".cython.score-30 {background-color: #FFFF3f;}\n",
".cython.score-31 {background-color: #FFFF3e;}\n",
".cython.score-32 {background-color: #FFFF3c;}\n",
".cython.score-33 {background-color: #FFFF3b;}\n",
".cython.score-34 {background-color: #FFFF39;}\n",
".cython.score-35 {background-color: #FFFF38;}\n",
".cython.score-36 {background-color: #FFFF37;}\n",
".cython.score-37 {background-color: #FFFF36;}\n",
".cython.score-38 {background-color: #FFFF35;}\n",
".cython.score-39 {background-color: #FFFF34;}\n",
".cython.score-40 {background-color: #FFFF33;}\n",
".cython.score-41 {background-color: #FFFF32;}\n",
".cython.score-42 {background-color: #FFFF31;}\n",
".cython.score-43 {background-color: #FFFF30;}\n",
".cython.score-44 {background-color: #FFFF2f;}\n",
".cython.score-45 {background-color: #FFFF2e;}\n",
".cython.score-46 {background-color: #FFFF2d;}\n",
".cython.score-47 {background-color: #FFFF2c;}\n",
".cython.score-48 {background-color: #FFFF2b;}\n",
".cython.score-49 {background-color: #FFFF2b;}\n",
".cython.score-50 {background-color: #FFFF2a;}\n",
".cython.score-51 {background-color: #FFFF29;}\n",
".cython.score-52 {background-color: #FFFF29;}\n",
".cython.score-53 {background-color: #FFFF28;}\n",
".cython.score-54 {background-color: #FFFF27;}\n",
".cython.score-55 {background-color: #FFFF27;}\n",
".cython.score-56 {background-color: #FFFF26;}\n",
".cython.score-57 {background-color: #FFFF26;}\n",
".cython.score-58 {background-color: #FFFF25;}\n",
".cython.score-59 {background-color: #FFFF24;}\n",
".cython.score-60 {background-color: #FFFF24;}\n",
".cython.score-61 {background-color: #FFFF23;}\n",
".cython.score-62 {background-color: #FFFF23;}\n",
".cython.score-63 {background-color: #FFFF22;}\n",
".cython.score-64 {background-color: #FFFF22;}\n",
".cython.score-65 {background-color: #FFFF22;}\n",
".cython.score-66 {background-color: #FFFF21;}\n",
".cython.score-67 {background-color: #FFFF21;}\n",
".cython.score-68 {background-color: #FFFF20;}\n",
".cython.score-69 {background-color: #FFFF20;}\n",
".cython.score-70 {background-color: #FFFF1f;}\n",
".cython.score-71 {background-color: #FFFF1f;}\n",
".cython.score-72 {background-color: #FFFF1f;}\n",
".cython.score-73 {background-color: #FFFF1e;}\n",
".cython.score-74 {background-color: #FFFF1e;}\n",
".cython.score-75 {background-color: #FFFF1e;}\n",
".cython.score-76 {background-color: #FFFF1d;}\n",
".cython.score-77 {background-color: #FFFF1d;}\n",
".cython.score-78 {background-color: #FFFF1c;}\n",
".cython.score-79 {background-color: #FFFF1c;}\n",
".cython.score-80 {background-color: #FFFF1c;}\n",
".cython.score-81 {background-color: #FFFF1c;}\n",
".cython.score-82 {background-color: #FFFF1b;}\n",
".cython.score-83 {background-color: #FFFF1b;}\n",
".cython.score-84 {background-color: #FFFF1b;}\n",
".cython.score-85 {background-color: #FFFF1a;}\n",
".cython.score-86 {background-color: #FFFF1a;}\n",
".cython.score-87 {background-color: #FFFF1a;}\n",
".cython.score-88 {background-color: #FFFF1a;}\n",
".cython.score-89 {background-color: #FFFF19;}\n",
".cython.score-90 {background-color: #FFFF19;}\n",
".cython.score-91 {background-color: #FFFF19;}\n",
".cython.score-92 {background-color: #FFFF19;}\n",
".cython.score-93 {background-color: #FFFF18;}\n",
".cython.score-94 {background-color: #FFFF18;}\n",
".cython.score-95 {background-color: #FFFF18;}\n",
".cython.score-96 {background-color: #FFFF18;}\n",
".cython.score-97 {background-color: #FFFF17;}\n",
".cython.score-98 {background-color: #FFFF17;}\n",
".cython.score-99 {background-color: #FFFF17;}\n",
".cython.score-100 {background-color: #FFFF17;}\n",
".cython.score-101 {background-color: #FFFF16;}\n",
".cython.score-102 {background-color: #FFFF16;}\n",
".cython.score-103 {background-color: #FFFF16;}\n",
".cython.score-104 {background-color: #FFFF16;}\n",
".cython.score-105 {background-color: #FFFF16;}\n",
".cython.score-106 {background-color: #FFFF15;}\n",
".cython.score-107 {background-color: #FFFF15;}\n",
".cython.score-108 {background-color: #FFFF15;}\n",
".cython.score-109 {background-color: #FFFF15;}\n",
".cython.score-110 {background-color: #FFFF15;}\n",
".cython.score-111 {background-color: #FFFF15;}\n",
".cython.score-112 {background-color: #FFFF14;}\n",
".cython.score-113 {background-color: #FFFF14;}\n",
".cython.score-114 {background-color: #FFFF14;}\n",
".cython.score-115 {background-color: #FFFF14;}\n",
".cython.score-116 {background-color: #FFFF14;}\n",
".cython.score-117 {background-color: #FFFF14;}\n",
".cython.score-118 {background-color: #FFFF13;}\n",
".cython.score-119 {background-color: #FFFF13;}\n",
".cython.score-120 {background-color: #FFFF13;}\n",
".cython.score-121 {background-color: #FFFF13;}\n",
".cython.score-122 {background-color: #FFFF13;}\n",
".cython.score-123 {background-color: #FFFF13;}\n",
".cython.score-124 {background-color: #FFFF13;}\n",
".cython.score-125 {background-color: #FFFF12;}\n",
".cython.score-126 {background-color: #FFFF12;}\n",
".cython.score-127 {background-color: #FFFF12;}\n",
".cython.score-128 {background-color: #FFFF12;}\n",
".cython.score-129 {background-color: #FFFF12;}\n",
".cython.score-130 {background-color: #FFFF12;}\n",
".cython.score-131 {background-color: #FFFF12;}\n",
".cython.score-132 {background-color: #FFFF11;}\n",
".cython.score-133 {background-color: #FFFF11;}\n",
".cython.score-134 {background-color: #FFFF11;}\n",
".cython.score-135 {background-color: #FFFF11;}\n",
".cython.score-136 {background-color: #FFFF11;}\n",
".cython.score-137 {background-color: #FFFF11;}\n",
".cython.score-138 {background-color: #FFFF11;}\n",
".cython.score-139 {background-color: #FFFF11;}\n",
".cython.score-140 {background-color: #FFFF11;}\n",
".cython.score-141 {background-color: #FFFF10;}\n",
".cython.score-142 {background-color: #FFFF10;}\n",
".cython.score-143 {background-color: #FFFF10;}\n",
".cython.score-144 {background-color: #FFFF10;}\n",
".cython.score-145 {background-color: #FFFF10;}\n",
".cython.score-146 {background-color: #FFFF10;}\n",
".cython.score-147 {background-color: #FFFF10;}\n",
".cython.score-148 {background-color: #FFFF10;}\n",
".cython.score-149 {background-color: #FFFF10;}\n",
".cython.score-150 {background-color: #FFFF0f;}\n",
".cython.score-151 {background-color: #FFFF0f;}\n",
".cython.score-152 {background-color: #FFFF0f;}\n",
".cython.score-153 {background-color: #FFFF0f;}\n",
".cython.score-154 {background-color: #FFFF0f;}\n",
".cython.score-155 {background-color: #FFFF0f;}\n",
".cython.score-156 {background-color: #FFFF0f;}\n",
".cython.score-157 {background-color: #FFFF0f;}\n",
".cython.score-158 {background-color: #FFFF0f;}\n",
".cython.score-159 {background-color: #FFFF0f;}\n",
".cython.score-160 {background-color: #FFFF0f;}\n",
".cython.score-161 {background-color: #FFFF0e;}\n",
".cython.score-162 {background-color: #FFFF0e;}\n",
".cython.score-163 {background-color: #FFFF0e;}\n",
".cython.score-164 {background-color: #FFFF0e;}\n",
".cython.score-165 {background-color: #FFFF0e;}\n",
".cython.score-166 {background-color: #FFFF0e;}\n",
".cython.score-167 {background-color: #FFFF0e;}\n",
".cython.score-168 {background-color: #FFFF0e;}\n",
".cython.score-169 {background-color: #FFFF0e;}\n",
".cython.score-170 {background-color: #FFFF0e;}\n",
".cython.score-171 {background-color: #FFFF0e;}\n",
".cython.score-172 {background-color: #FFFF0e;}\n",
".cython.score-173 {background-color: #FFFF0d;}\n",
".cython.score-174 {background-color: #FFFF0d;}\n",
".cython.score-175 {background-color: #FFFF0d;}\n",
".cython.score-176 {background-color: #FFFF0d;}\n",
".cython.score-177 {background-color: #FFFF0d;}\n",
".cython.score-178 {background-color: #FFFF0d;}\n",
".cython.score-179 {background-color: #FFFF0d;}\n",
".cython.score-180 {background-color: #FFFF0d;}\n",
".cython.score-181 {background-color: #FFFF0d;}\n",
".cython.score-182 {background-color: #FFFF0d;}\n",
".cython.score-183 {background-color: #FFFF0d;}\n",
".cython.score-184 {background-color: #FFFF0d;}\n",
".cython.score-185 {background-color: #FFFF0d;}\n",
".cython.score-186 {background-color: #FFFF0d;}\n",
".cython.score-187 {background-color: #FFFF0c;}\n",
".cython.score-188 {background-color: #FFFF0c;}\n",
".cython.score-189 {background-color: #FFFF0c;}\n",
".cython.score-190 {background-color: #FFFF0c;}\n",
".cython.score-191 {background-color: #FFFF0c;}\n",
".cython.score-192 {background-color: #FFFF0c;}\n",
".cython.score-193 {background-color: #FFFF0c;}\n",
".cython.score-194 {background-color: #FFFF0c;}\n",
".cython.score-195 {background-color: #FFFF0c;}\n",
".cython.score-196 {background-color: #FFFF0c;}\n",
".cython.score-197 {background-color: #FFFF0c;}\n",
".cython.score-198 {background-color: #FFFF0c;}\n",
".cython.score-199 {background-color: #FFFF0c;}\n",
".cython.score-200 {background-color: #FFFF0c;}\n",
".cython.score-201 {background-color: #FFFF0c;}\n",
".cython.score-202 {background-color: #FFFF0c;}\n",
".cython.score-203 {background-color: #FFFF0b;}\n",
".cython.score-204 {background-color: #FFFF0b;}\n",
".cython.score-205 {background-color: #FFFF0b;}\n",
".cython.score-206 {background-color: #FFFF0b;}\n",
".cython.score-207 {background-color: #FFFF0b;}\n",
".cython.score-208 {background-color: #FFFF0b;}\n",
".cython.score-209 {background-color: #FFFF0b;}\n",
".cython.score-210 {background-color: #FFFF0b;}\n",
".cython.score-211 {background-color: #FFFF0b;}\n",
".cython.score-212 {background-color: #FFFF0b;}\n",
".cython.score-213 {background-color: #FFFF0b;}\n",
".cython.score-214 {background-color: #FFFF0b;}\n",
".cython.score-215 {background-color: #FFFF0b;}\n",
".cython.score-216 {background-color: #FFFF0b;}\n",
".cython.score-217 {background-color: #FFFF0b;}\n",
".cython.score-218 {background-color: #FFFF0b;}\n",
".cython.score-219 {background-color: #FFFF0b;}\n",
".cython.score-220 {background-color: #FFFF0b;}\n",
".cython.score-221 {background-color: #FFFF0b;}\n",
".cython.score-222 {background-color: #FFFF0a;}\n",
".cython.score-223 {background-color: #FFFF0a;}\n",
".cython.score-224 {background-color: #FFFF0a;}\n",
".cython.score-225 {background-color: #FFFF0a;}\n",
".cython.score-226 {background-color: #FFFF0a;}\n",
".cython.score-227 {background-color: #FFFF0a;}\n",
".cython.score-228 {background-color: #FFFF0a;}\n",
".cython.score-229 {background-color: #FFFF0a;}\n",
".cython.score-230 {background-color: #FFFF0a;}\n",
".cython.score-231 {background-color: #FFFF0a;}\n",
".cython.score-232 {background-color: #FFFF0a;}\n",
".cython.score-233 {background-color: #FFFF0a;}\n",
".cython.score-234 {background-color: #FFFF0a;}\n",
".cython.score-235 {background-color: #FFFF0a;}\n",
".cython.score-236 {background-color: #FFFF0a;}\n",
".cython.score-237 {background-color: #FFFF0a;}\n",
".cython.score-238 {background-color: #FFFF0a;}\n",
".cython.score-239 {background-color: #FFFF0a;}\n",
".cython.score-240 {background-color: #FFFF0a;}\n",
".cython.score-241 {background-color: #FFFF0a;}\n",
".cython.score-242 {background-color: #FFFF0a;}\n",
".cython.score-243 {background-color: #FFFF0a;}\n",
".cython.score-244 {background-color: #FFFF0a;}\n",
".cython.score-245 {background-color: #FFFF0a;}\n",
".cython.score-246 {background-color: #FFFF09;}\n",
".cython.score-247 {background-color: #FFFF09;}\n",
".cython.score-248 {background-color: #FFFF09;}\n",
".cython.score-249 {background-color: #FFFF09;}\n",
".cython.score-250 {background-color: #FFFF09;}\n",
".cython.score-251 {background-color: #FFFF09;}\n",
".cython.score-252 {background-color: #FFFF09;}\n",
".cython.score-253 {background-color: #FFFF09;}\n",
".cython.score-254 {background-color: #FFFF09;}.cython .hll { background-color: #ffffcc }\n",
".cython { background: #f8f8f8; }\n",
".cython .c { color: #408080; font-style: italic } /* Comment */\n",
".cython .err { border: 1px solid #FF0000 } /* Error */\n",
".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
".cython .o { color: #666666 } /* Operator */\n",
".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
".cython .ge { font-style: italic } /* Generic.Emph */\n",
".cython .gr { color: #FF0000 } /* Generic.Error */\n",
".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
".cython .go { color: #888888 } /* Generic.Output */\n",
".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
".cython .gs { font-weight: bold } /* Generic.Strong */\n",
".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
".cython .kt { color: #B00040 } /* Keyword.Type */\n",
".cython .m { color: #666666 } /* Literal.Number */\n",
".cython .s { color: #BA2121 } /* Literal.String */\n",
".cython .na { color: #7D9029 } /* Name.Attribute */\n",
".cython .nb { color: #008000 } /* Name.Builtin */\n",
".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
".cython .no { color: #880000 } /* Name.Constant */\n",
".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
".cython .nf { color: #0000FF } /* Name.Function */\n",
".cython .nl { color: #A0A000 } /* Name.Label */\n",
".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
".cython .nv { color: #19177C } /* Name.Variable */\n",
".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
".cython .sx { color: #008000 } /* Literal.String.Other */\n",
".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
" </style>\n",
" <script>\n",
" function toggleDiv(id) {\n",
" theDiv = id.nextElementSibling\n",
" if (theDiv.style.display != 'block') theDiv.style.display = 'block';\n",
" else theDiv.style.display = 'none';\n",
" }\n",
" </script>\n",
"</head>\n",
"<body class=\"cython\">\n",
"<p>Generated by Cython 0.22</p>\n",
"<div class=\"cython\"><pre class='cython line score-0'>&#xA0;01: </pre>\n",
"<pre class='cython line score-8' onclick='toggleDiv(this)'>+02: <span class=\"k\">import</span> <span class=\"nn\">math</span></pre>\n",
"<pre class='cython code score-8'> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_Import</span>(__pyx_n_s_math, 0, -1);<span class='error_goto'> if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_math, __pyx_t_1) &lt; 0) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
"</pre><pre class='cython line score-0'>&#xA0;03: </pre>\n",
"<pre class='cython line score-58' onclick='toggleDiv(this)'>+04: <span class=\"k\">def</span> <span class=\"nf\">slope_cython1</span><span class=\"p\">(</span><span class=\"n\">indata</span><span class=\"p\">,</span> <span class=\"n\">outdata</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-58'>/* Python wrapper */\n",
"static PyObject *__pyx_pw_46_cython_magic_5ce0ea3363e793331bdc8fd26ebbeb92_1slope_cython1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
"static PyMethodDef __pyx_mdef_46_cython_magic_5ce0ea3363e793331bdc8fd26ebbeb92_1slope_cython1 = {\"slope_cython1\", (PyCFunction)__pyx_pw_46_cython_magic_5ce0ea3363e793331bdc8fd26ebbeb92_1slope_cython1, METH_VARARGS|METH_KEYWORDS, 0};\n",
"static PyObject *__pyx_pw_46_cython_magic_5ce0ea3363e793331bdc8fd26ebbeb92_1slope_cython1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
" PyObject *__pyx_v_indata = 0;\n",
" PyObject *__pyx_v_outdata = 0;\n",
" PyObject *__pyx_r = 0;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"slope_cython1 (wrapper)\", 0);\n",
" {\n",
" static PyObject **__pyx_pyargnames[] = {&amp;__pyx_n_s_indata,&amp;__pyx_n_s_outdata,0};\n",
" PyObject* values[2] = {0,0};\n",
" if (unlikely(__pyx_kwds)) {\n",
" Py_ssize_t kw_args;\n",
" const Py_ssize_t pos_args = <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args);\n",
" switch (pos_args) {\n",
" case 2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" case 1: values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" case 0: break;\n",
" default: goto __pyx_L5_argtuple_error;\n",
" }\n",
" kw_args = <span class='py_c_api'>PyDict_Size</span>(__pyx_kwds);\n",
" switch (pos_args) {\n",
" case 0:\n",
" if (likely((values[0] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_indata)) != 0)) kw_args--;\n",
" else goto __pyx_L5_argtuple_error;\n",
" case 1:\n",
" if (likely((values[1] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_outdata)) != 0)) kw_args--;\n",
" else {\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"slope_cython1\", 1, 2, 2, 1); <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" }\n",
" }\n",
" if (unlikely(kw_args &gt; 0)) {\n",
" if (unlikely(<span class='pyx_c_api'>__Pyx_ParseOptionalKeywords</span>(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"slope_cython1\") &lt; 0)) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" }\n",
" } else if (<span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args) != 2) {\n",
" goto __pyx_L5_argtuple_error;\n",
" } else {\n",
" values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" }\n",
" __pyx_v_indata = values[0];\n",
" __pyx_v_outdata = values[1];\n",
" }\n",
" goto __pyx_L4_argument_unpacking_done;\n",
" __pyx_L5_argtuple_error:;\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"slope_cython1\", 1, 2, 2, <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)); <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" __pyx_L3_error:;\n",
" <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_5ce0ea3363e793331bdc8fd26ebbeb92.slope_cython1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
" <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
" return NULL;\n",
" __pyx_L4_argument_unpacking_done:;\n",
" __pyx_r = __pyx_pf_46_cython_magic_5ce0ea3363e793331bdc8fd26ebbeb92_slope_cython1(__pyx_self, __pyx_v_indata, __pyx_v_outdata);\n",
" int __pyx_lineno = 0;\n",
" const char *__pyx_filename = NULL;\n",
" int __pyx_clineno = 0;\n",
"\n",
" /* function exit code */\n",
" <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
" return __pyx_r;\n",
"}\n",
"\n",
"static PyObject *__pyx_pf_46_cython_magic_5ce0ea3363e793331bdc8fd26ebbeb92_slope_cython1(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_indata, PyObject *__pyx_v_outdata) {\n",
" PyObject *__pyx_v_I = NULL;\n",
" PyObject *__pyx_v_J = NULL;\n",
" PyObject *__pyx_v_i = NULL;\n",
" PyObject *__pyx_v_j = NULL;\n",
" PyObject *__pyx_v_dzdx = NULL;\n",
" PyObject *__pyx_v_dzdy = NULL;\n",
" PyObject *__pyx_v_slp = NULL;\n",
" PyObject *__pyx_r = NULL;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"slope_cython1\", 0);\n",
"/* … */\n",
" /* function exit code */\n",
" __pyx_r = Py_None; <span class='pyx_macro_api'>__Pyx_INCREF</span>(Py_None);\n",
" goto __pyx_L0;\n",
" __pyx_L1_error:;\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_1);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_8);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_9);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_10);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_11);\n",
" <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_5ce0ea3363e793331bdc8fd26ebbeb92.slope_cython1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
" __pyx_r = NULL;\n",
" __pyx_L0:;\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_I);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_J);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_i);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_j);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_dzdx);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_dzdy);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_slp);\n",
" <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
" <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
" return __pyx_r;\n",
"}\n",
"/* … */\n",
" __pyx_tuple_ = <span class='py_c_api'>PyTuple_Pack</span>(9, __pyx_n_s_indata, __pyx_n_s_outdata, __pyx_n_s_I, __pyx_n_s_J, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_dzdx, __pyx_n_s_dzdy, __pyx_n_s_slp);<span class='error_goto'> if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple_);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple_);\n",
"/* … */\n",
" __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_5ce0ea3363e793331bdc8fd26ebbeb92_1slope_cython1, NULL, __pyx_n_s_cython_magic_5ce0ea3363e793331b);<span class='error_goto'> if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_slope_cython1, __pyx_t_1) &lt; 0) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
"</pre><pre class='cython line score-5' onclick='toggleDiv(this)'>+05: <span class=\"n\">I</span> <span class=\"o\">=</span> <span class=\"n\">outdata</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-5'> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_v_outdata, __pyx_n_s_shape);<span class='error_goto'> if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" __pyx_t_2 = <span class='pyx_c_api'>__Pyx_GetItemInt</span>(__pyx_t_1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1);<span class='error_goto'> if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_v_I = __pyx_t_2;\n",
" __pyx_t_2 = 0;\n",
"</pre><pre class='cython line score-5' onclick='toggleDiv(this)'>+06: <span class=\"n\">J</span> <span class=\"o\">=</span> <span class=\"n\">outdata</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">1</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-5'> __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_v_outdata, __pyx_n_s_shape);<span class='error_goto'> if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_GetItemInt</span>(__pyx_t_2, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1);<span class='error_goto'> if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" __pyx_v_J = __pyx_t_1;\n",
" __pyx_t_1 = 0;\n",
"</pre><pre class='cython line score-57' onclick='toggleDiv(this)'>+07: <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">I</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-57'> __pyx_t_1 = <span class='py_c_api'>PyTuple_New</span>(1);<span class='error_goto'> if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_I);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_1, 0, __pyx_v_I);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_I);\n",
" __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_builtin_range, __pyx_t_1, NULL);<span class='error_goto'> if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" if (likely(<span class='py_c_api'>PyList_CheckExact</span>(__pyx_t_2)) || <span class='py_c_api'>PyTuple_CheckExact</span>(__pyx_t_2)) {\n",
" __pyx_t_1 = __pyx_t_2; <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_1); __pyx_t_3 = 0;\n",
" __pyx_t_4 = NULL;\n",
" } else {\n",
" __pyx_t_3 = -1; __pyx_t_1 = <span class='py_c_api'>PyObject_GetIter</span>(__pyx_t_2);<span class='error_goto'> if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" __pyx_t_4 = Py_TYPE(__pyx_t_1)-&gt;tp_iternext;<span class='error_goto'> if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" }\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" for (;;) {\n",
" if (likely(!__pyx_t_4)) {\n",
" if (likely(<span class='py_c_api'>PyList_CheckExact</span>(__pyx_t_1))) {\n",
" if (__pyx_t_3 &gt;= <span class='py_macro_api'>PyList_GET_SIZE</span>(__pyx_t_1)) break;\n",
" #if CYTHON_COMPILING_IN_CPYTHON\n",
" __pyx_t_2 = <span class='py_macro_api'>PyList_GET_ITEM</span>(__pyx_t_1, __pyx_t_3); <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_2); __pyx_t_3++;<span class='error_goto'> if (unlikely(0 &lt; 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" #else\n",
" __pyx_t_2 = <span class='py_macro_api'>PySequence_ITEM</span>(__pyx_t_1, __pyx_t_3); __pyx_t_3++;<span class='error_goto'> if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" #endif\n",
" } else {\n",
" if (__pyx_t_3 &gt;= <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_t_1)) break;\n",
" #if CYTHON_COMPILING_IN_CPYTHON\n",
" __pyx_t_2 = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_t_1, __pyx_t_3); <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_2); __pyx_t_3++;<span class='error_goto'> if (unlikely(0 &lt; 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" #else\n",
" __pyx_t_2 = <span class='py_macro_api'>PySequence_ITEM</span>(__pyx_t_1, __pyx_t_3); __pyx_t_3++;<span class='error_goto'> if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" #endif\n",
" }\n",
" } else {\n",
" __pyx_t_2 = __pyx_t_4(__pyx_t_1);\n",
" if (unlikely(!__pyx_t_2)) {\n",
" PyObject* exc_type = <span class='py_c_api'>PyErr_Occurred</span>();\n",
" if (exc_type) {\n",
" if (likely(exc_type == PyExc_StopIteration || <span class='py_c_api'>PyErr_GivenExceptionMatches</span>(exc_type, PyExc_StopIteration))) <span class='py_c_api'>PyErr_Clear</span>();\n",
" else <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" }\n",
" break;\n",
" }\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" }\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF_SET</span>(__pyx_v_i, __pyx_t_2);\n",
" __pyx_t_2 = 0;\n",
"/* … */\n",
" }\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
"</pre><pre class='cython line score-57' onclick='toggleDiv(this)'>+08: <span class=\"k\">for</span> <span class=\"n\">j</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">J</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-57'> __pyx_t_2 = <span class='py_c_api'>PyTuple_New</span>(1);<span class='error_goto'> if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_J);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_2, 0, __pyx_v_J);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_J);\n",
" __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_builtin_range, __pyx_t_2, NULL);<span class='error_goto'> if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" if (likely(<span class='py_c_api'>PyList_CheckExact</span>(__pyx_t_5)) || <span class='py_c_api'>PyTuple_CheckExact</span>(__pyx_t_5)) {\n",
" __pyx_t_2 = __pyx_t_5; <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_2); __pyx_t_6 = 0;\n",
" __pyx_t_7 = NULL;\n",
" } else {\n",
" __pyx_t_6 = -1; __pyx_t_2 = <span class='py_c_api'>PyObject_GetIter</span>(__pyx_t_5);<span class='error_goto'> if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" __pyx_t_7 = Py_TYPE(__pyx_t_2)-&gt;tp_iternext;<span class='error_goto'> if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" }\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
" for (;;) {\n",
" if (likely(!__pyx_t_7)) {\n",
" if (likely(<span class='py_c_api'>PyList_CheckExact</span>(__pyx_t_2))) {\n",
" if (__pyx_t_6 &gt;= <span class='py_macro_api'>PyList_GET_SIZE</span>(__pyx_t_2)) break;\n",
" #if CYTHON_COMPILING_IN_CPYTHON\n",
" __pyx_t_5 = <span class='py_macro_api'>PyList_GET_ITEM</span>(__pyx_t_2, __pyx_t_6); <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_5); __pyx_t_6++;<span class='error_goto'> if (unlikely(0 &lt; 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" #else\n",
" __pyx_t_5 = <span class='py_macro_api'>PySequence_ITEM</span>(__pyx_t_2, __pyx_t_6); __pyx_t_6++;<span class='error_goto'> if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" #endif\n",
" } else {\n",
" if (__pyx_t_6 &gt;= <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_t_2)) break;\n",
" #if CYTHON_COMPILING_IN_CPYTHON\n",
" __pyx_t_5 = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_t_2, __pyx_t_6); <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_5); __pyx_t_6++;<span class='error_goto'> if (unlikely(0 &lt; 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" #else\n",
" __pyx_t_5 = <span class='py_macro_api'>PySequence_ITEM</span>(__pyx_t_2, __pyx_t_6); __pyx_t_6++;<span class='error_goto'> if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" #endif\n",
" }\n",
" } else {\n",
" __pyx_t_5 = __pyx_t_7(__pyx_t_2);\n",
" if (unlikely(!__pyx_t_5)) {\n",
" PyObject* exc_type = <span class='py_c_api'>PyErr_Occurred</span>();\n",
" if (exc_type) {\n",
" if (likely(exc_type == PyExc_StopIteration || <span class='py_c_api'>PyErr_GivenExceptionMatches</span>(exc_type, PyExc_StopIteration))) <span class='py_c_api'>PyErr_Clear</span>();\n",
" else <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" }\n",
" break;\n",
" }\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
" }\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF_SET</span>(__pyx_v_j, __pyx_t_5);\n",
" __pyx_t_5 = 0;\n",
"/* … */\n",
" }\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
"</pre><pre class='cython line score-53' onclick='toggleDiv(this)'>+09: <span class=\"n\">dzdx</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"p\">]</span> <span class=\"o\">-</span> <span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"o\">+</span><span class=\"mf\">2</span><span class=\"p\">])</span> <span class=\"o\">/</span> <span class=\"mf\">2</span></pre>\n",
"<pre class='cython code score-53'> __pyx_t_5 = <span class='py_c_api'>PyNumber_Add</span>(__pyx_v_i, __pyx_int_1);<span class='error_goto'> if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
" __pyx_t_8 = <span class='py_c_api'>PyTuple_New</span>(2);<span class='error_goto'> if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_8);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_8, 0, __pyx_t_5);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_5);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_j);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_8, 1, __pyx_v_j);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_j);\n",
" __pyx_t_5 = 0;\n",
" __pyx_t_5 = <span class='py_c_api'>PyObject_GetItem</span>(__pyx_v_indata, __pyx_t_8);<span class='error_goto'> if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_8); __pyx_t_8 = 0;\n",
" __pyx_t_8 = <span class='py_c_api'>PyNumber_Add</span>(__pyx_v_i, __pyx_int_1);<span class='error_goto'> if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_8);\n",
" __pyx_t_9 = <span class='py_c_api'>PyNumber_Add</span>(__pyx_v_j, __pyx_int_2);<span class='error_goto'> if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_9);\n",
" __pyx_t_10 = <span class='py_c_api'>PyTuple_New</span>(2);<span class='error_goto'> if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_10);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_10, 0, __pyx_t_8);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_8);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_10, 1, __pyx_t_9);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_9);\n",
" __pyx_t_8 = 0;\n",
" __pyx_t_9 = 0;\n",
" __pyx_t_9 = <span class='py_c_api'>PyObject_GetItem</span>(__pyx_v_indata, __pyx_t_10);<span class='error_goto'> if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_9);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_10); __pyx_t_10 = 0;\n",
" __pyx_t_10 = <span class='py_c_api'>PyNumber_Subtract</span>(__pyx_t_5, __pyx_t_9);<span class='error_goto'> if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_10);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_9); __pyx_t_9 = 0;\n",
" __pyx_t_9 = <span class='pyx_c_api'>__Pyx_PyNumber_Divide</span>(__pyx_t_10, __pyx_int_2);<span class='error_goto'> if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_9);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_10); __pyx_t_10 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF_SET</span>(__pyx_v_dzdx, __pyx_t_9);\n",
" __pyx_t_9 = 0;\n",
"</pre><pre class='cython line score-53' onclick='toggleDiv(this)'>+10: <span class=\"n\">dzdy</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"o\">-</span> <span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">2</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">])</span> <span class=\"o\">/</span> <span class=\"mf\">2</span></pre>\n",
"<pre class='cython code score-53'> __pyx_t_9 = <span class='py_c_api'>PyNumber_Add</span>(__pyx_v_j, __pyx_int_1);<span class='error_goto'> if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_9);\n",
" __pyx_t_10 = <span class='py_c_api'>PyTuple_New</span>(2);<span class='error_goto'> if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_10);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_i);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_10, 0, __pyx_v_i);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_i);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_10, 1, __pyx_t_9);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_9);\n",
" __pyx_t_9 = 0;\n",
" __pyx_t_9 = <span class='py_c_api'>PyObject_GetItem</span>(__pyx_v_indata, __pyx_t_10);<span class='error_goto'> if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_9);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_10); __pyx_t_10 = 0;\n",
" __pyx_t_10 = <span class='py_c_api'>PyNumber_Add</span>(__pyx_v_i, __pyx_int_2);<span class='error_goto'> if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_10);\n",
" __pyx_t_5 = <span class='py_c_api'>PyNumber_Add</span>(__pyx_v_j, __pyx_int_1);<span class='error_goto'> if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
" __pyx_t_8 = <span class='py_c_api'>PyTuple_New</span>(2);<span class='error_goto'> if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_8);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_8, 0, __pyx_t_10);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_10);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_8, 1, __pyx_t_5);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_5);\n",
" __pyx_t_10 = 0;\n",
" __pyx_t_5 = 0;\n",
" __pyx_t_5 = <span class='py_c_api'>PyObject_GetItem</span>(__pyx_v_indata, __pyx_t_8);<span class='error_goto'> if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_8); __pyx_t_8 = 0;\n",
" __pyx_t_8 = <span class='py_c_api'>PyNumber_Subtract</span>(__pyx_t_9, __pyx_t_5);<span class='error_goto'> if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_8);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_9); __pyx_t_9 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
" __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyNumber_Divide</span>(__pyx_t_8, __pyx_int_2);<span class='error_goto'> if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_8); __pyx_t_8 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF_SET</span>(__pyx_v_dzdy, __pyx_t_5);\n",
" __pyx_t_5 = 0;\n",
"</pre><pre class='cython line score-53' onclick='toggleDiv(this)'>+11: <span class=\"n\">slp</span> <span class=\"o\">=</span> <span class=\"n\">math</span><span class=\"o\">.</span><span class=\"n\">sqrt</span><span class=\"p\">((</span><span class=\"n\">dzdx</span> <span class=\"o\">*</span> <span class=\"n\">dzdx</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"p\">(</span><span class=\"n\">dzdy</span> <span class=\"o\">*</span> <span class=\"n\">dzdy</span><span class=\"p\">))</span> <span class=\"o\">*</span> <span class=\"mf\">100</span></pre>\n",
"<pre class='cython code score-53'> __pyx_t_8 = <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_n_s_math);<span class='error_goto'> if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_8);\n",
" __pyx_t_9 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_8, __pyx_n_s_sqrt);<span class='error_goto'> if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_9);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_8); __pyx_t_8 = 0;\n",
" __pyx_t_8 = <span class='py_c_api'>PyNumber_Multiply</span>(__pyx_v_dzdx, __pyx_v_dzdx);<span class='error_goto'> if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_8);\n",
" __pyx_t_10 = <span class='py_c_api'>PyNumber_Multiply</span>(__pyx_v_dzdy, __pyx_v_dzdy);<span class='error_goto'> if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_10);\n",
" __pyx_t_11 = <span class='py_c_api'>PyNumber_Add</span>(__pyx_t_8, __pyx_t_10);<span class='error_goto'> if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_11);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_8); __pyx_t_8 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_10); __pyx_t_10 = 0;\n",
" __pyx_t_10 = NULL;\n",
" if (CYTHON_COMPILING_IN_CPYTHON &amp;&amp; unlikely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_9))) {\n",
" __pyx_t_10 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_9);\n",
" if (likely(__pyx_t_10)) {\n",
" PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_9);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_10);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_9, function);\n",
" }\n",
" }\n",
" if (!__pyx_t_10) {\n",
" __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_9, __pyx_t_11);<span class='error_goto'> if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_11); __pyx_t_11 = 0;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
" } else {\n",
" __pyx_t_8 = <span class='py_c_api'>PyTuple_New</span>(1+1);<span class='error_goto'> if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_8);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_8, 0, __pyx_t_10); <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_10); __pyx_t_10 = NULL;\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_8, 0+1, __pyx_t_11);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_11);\n",
" __pyx_t_11 = 0;\n",
" __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_t_9, __pyx_t_8, NULL);<span class='error_goto'> if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_8); __pyx_t_8 = 0;\n",
" }\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_9); __pyx_t_9 = 0;\n",
" __pyx_t_9 = <span class='py_c_api'>PyNumber_Multiply</span>(__pyx_t_5, __pyx_int_100);<span class='error_goto'> if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_9);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF_SET</span>(__pyx_v_slp, __pyx_t_9);\n",
" __pyx_t_9 = 0;\n",
"</pre><pre class='cython line score-15' onclick='toggleDiv(this)'>+12: <span class=\"n\">outdata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">slp</span></pre>\n",
"<pre class='cython code score-15'> __pyx_t_9 = <span class='py_c_api'>PyTuple_New</span>(2);<span class='error_goto'> if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_9);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_i);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_9, 0, __pyx_v_i);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_i);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_j);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_9, 1, __pyx_v_j);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_j);\n",
" if (unlikely(<span class='py_c_api'>PyObject_SetItem</span>(__pyx_v_outdata, __pyx_t_9, __pyx_v_slp) &lt; 0)) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_9); __pyx_t_9 = 0;\n",
"</pre></div></body></html>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%cython -a\n",
"\n",
"import math\n",
"\n",
"def slope_cython1(indata, outdata):\n",
" I = outdata.shape[0]\n",
" J = outdata.shape[1]\n",
" for i in range(I):\n",
" for j in range(J):\n",
" dzdx = (indata[i+1, j] - indata[i+1, j+2]) / 2\n",
" dzdy = (indata[i, j+1] - indata[i+2, j+1]) / 2\n",
" slp = math.sqrt((dzdx * dzdx) + (dzdy * dzdy)) * 100\n",
" outdata[i, j] = slp"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The yellow indicates calls into Python functions which generally means that you're not getting the speed benefits of pure C. This is unsurprising since the code is exactly the same python code we ran before, minus the comments. And the performance is similar:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1 loops, best of 3: 8.36 s per loop\n"
]
}
],
"source": [
"reset_outdata()\n",
"%timeit slope_cython1(indata, outdata)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We only get the speedups when we start optimizing the code by typing the variables, avoiding the use of the `math` lib, and omitting some bounds checking. This allows the function to be run in pure C and not touch the python interpreter."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<!DOCTYPE html>\n",
"<!-- Generated by Cython 0.22 -->\n",
"<html>\n",
"<head>\n",
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
" <style type=\"text/css\">\n",
" \n",
"body.cython { font-family: courier; font-size: 12; }\n",
"\n",
".cython.tag { }\n",
".cython.line { margin: 0em }\n",
".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 20px; }\n",
"\n",
".cython.code .py_c_api { color: red; }\n",
".cython.code .py_macro_api { color: #FF7000; }\n",
".cython.code .pyx_c_api { color: #FF3000; }\n",
".cython.code .pyx_macro_api { color: #FF7000; }\n",
".cython.code .refnanny { color: #FFA000; }\n",
".cython.code .error_goto { color: #FFA000; }\n",
"\n",
".cython.code .coerce { color: #008000; border: 1px dotted #008000 }\n",
".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
".cython.code .c_attr { color: #0000FF; }\n",
".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
".cython.code .c_call { color: #0000FF; }\n",
"\n",
".cython.score-0 {background-color: #FFFFff;}\n",
".cython.score-1 {background-color: #FFFFe7;}\n",
".cython.score-2 {background-color: #FFFFd4;}\n",
".cython.score-3 {background-color: #FFFFc4;}\n",
".cython.score-4 {background-color: #FFFFb6;}\n",
".cython.score-5 {background-color: #FFFFaa;}\n",
".cython.score-6 {background-color: #FFFF9f;}\n",
".cython.score-7 {background-color: #FFFF96;}\n",
".cython.score-8 {background-color: #FFFF8d;}\n",
".cython.score-9 {background-color: #FFFF86;}\n",
".cython.score-10 {background-color: #FFFF7f;}\n",
".cython.score-11 {background-color: #FFFF79;}\n",
".cython.score-12 {background-color: #FFFF73;}\n",
".cython.score-13 {background-color: #FFFF6e;}\n",
".cython.score-14 {background-color: #FFFF6a;}\n",
".cython.score-15 {background-color: #FFFF66;}\n",
".cython.score-16 {background-color: #FFFF62;}\n",
".cython.score-17 {background-color: #FFFF5e;}\n",
".cython.score-18 {background-color: #FFFF5b;}\n",
".cython.score-19 {background-color: #FFFF57;}\n",
".cython.score-20 {background-color: #FFFF55;}\n",
".cython.score-21 {background-color: #FFFF52;}\n",
".cython.score-22 {background-color: #FFFF4f;}\n",
".cython.score-23 {background-color: #FFFF4d;}\n",
".cython.score-24 {background-color: #FFFF4b;}\n",
".cython.score-25 {background-color: #FFFF48;}\n",
".cython.score-26 {background-color: #FFFF46;}\n",
".cython.score-27 {background-color: #FFFF44;}\n",
".cython.score-28 {background-color: #FFFF43;}\n",
".cython.score-29 {background-color: #FFFF41;}\n",
".cython.score-30 {background-color: #FFFF3f;}\n",
".cython.score-31 {background-color: #FFFF3e;}\n",
".cython.score-32 {background-color: #FFFF3c;}\n",
".cython.score-33 {background-color: #FFFF3b;}\n",
".cython.score-34 {background-color: #FFFF39;}\n",
".cython.score-35 {background-color: #FFFF38;}\n",
".cython.score-36 {background-color: #FFFF37;}\n",
".cython.score-37 {background-color: #FFFF36;}\n",
".cython.score-38 {background-color: #FFFF35;}\n",
".cython.score-39 {background-color: #FFFF34;}\n",
".cython.score-40 {background-color: #FFFF33;}\n",
".cython.score-41 {background-color: #FFFF32;}\n",
".cython.score-42 {background-color: #FFFF31;}\n",
".cython.score-43 {background-color: #FFFF30;}\n",
".cython.score-44 {background-color: #FFFF2f;}\n",
".cython.score-45 {background-color: #FFFF2e;}\n",
".cython.score-46 {background-color: #FFFF2d;}\n",
".cython.score-47 {background-color: #FFFF2c;}\n",
".cython.score-48 {background-color: #FFFF2b;}\n",
".cython.score-49 {background-color: #FFFF2b;}\n",
".cython.score-50 {background-color: #FFFF2a;}\n",
".cython.score-51 {background-color: #FFFF29;}\n",
".cython.score-52 {background-color: #FFFF29;}\n",
".cython.score-53 {background-color: #FFFF28;}\n",
".cython.score-54 {background-color: #FFFF27;}\n",
".cython.score-55 {background-color: #FFFF27;}\n",
".cython.score-56 {background-color: #FFFF26;}\n",
".cython.score-57 {background-color: #FFFF26;}\n",
".cython.score-58 {background-color: #FFFF25;}\n",
".cython.score-59 {background-color: #FFFF24;}\n",
".cython.score-60 {background-color: #FFFF24;}\n",
".cython.score-61 {background-color: #FFFF23;}\n",
".cython.score-62 {background-color: #FFFF23;}\n",
".cython.score-63 {background-color: #FFFF22;}\n",
".cython.score-64 {background-color: #FFFF22;}\n",
".cython.score-65 {background-color: #FFFF22;}\n",
".cython.score-66 {background-color: #FFFF21;}\n",
".cython.score-67 {background-color: #FFFF21;}\n",
".cython.score-68 {background-color: #FFFF20;}\n",
".cython.score-69 {background-color: #FFFF20;}\n",
".cython.score-70 {background-color: #FFFF1f;}\n",
".cython.score-71 {background-color: #FFFF1f;}\n",
".cython.score-72 {background-color: #FFFF1f;}\n",
".cython.score-73 {background-color: #FFFF1e;}\n",
".cython.score-74 {background-color: #FFFF1e;}\n",
".cython.score-75 {background-color: #FFFF1e;}\n",
".cython.score-76 {background-color: #FFFF1d;}\n",
".cython.score-77 {background-color: #FFFF1d;}\n",
".cython.score-78 {background-color: #FFFF1c;}\n",
".cython.score-79 {background-color: #FFFF1c;}\n",
".cython.score-80 {background-color: #FFFF1c;}\n",
".cython.score-81 {background-color: #FFFF1c;}\n",
".cython.score-82 {background-color: #FFFF1b;}\n",
".cython.score-83 {background-color: #FFFF1b;}\n",
".cython.score-84 {background-color: #FFFF1b;}\n",
".cython.score-85 {background-color: #FFFF1a;}\n",
".cython.score-86 {background-color: #FFFF1a;}\n",
".cython.score-87 {background-color: #FFFF1a;}\n",
".cython.score-88 {background-color: #FFFF1a;}\n",
".cython.score-89 {background-color: #FFFF19;}\n",
".cython.score-90 {background-color: #FFFF19;}\n",
".cython.score-91 {background-color: #FFFF19;}\n",
".cython.score-92 {background-color: #FFFF19;}\n",
".cython.score-93 {background-color: #FFFF18;}\n",
".cython.score-94 {background-color: #FFFF18;}\n",
".cython.score-95 {background-color: #FFFF18;}\n",
".cython.score-96 {background-color: #FFFF18;}\n",
".cython.score-97 {background-color: #FFFF17;}\n",
".cython.score-98 {background-color: #FFFF17;}\n",
".cython.score-99 {background-color: #FFFF17;}\n",
".cython.score-100 {background-color: #FFFF17;}\n",
".cython.score-101 {background-color: #FFFF16;}\n",
".cython.score-102 {background-color: #FFFF16;}\n",
".cython.score-103 {background-color: #FFFF16;}\n",
".cython.score-104 {background-color: #FFFF16;}\n",
".cython.score-105 {background-color: #FFFF16;}\n",
".cython.score-106 {background-color: #FFFF15;}\n",
".cython.score-107 {background-color: #FFFF15;}\n",
".cython.score-108 {background-color: #FFFF15;}\n",
".cython.score-109 {background-color: #FFFF15;}\n",
".cython.score-110 {background-color: #FFFF15;}\n",
".cython.score-111 {background-color: #FFFF15;}\n",
".cython.score-112 {background-color: #FFFF14;}\n",
".cython.score-113 {background-color: #FFFF14;}\n",
".cython.score-114 {background-color: #FFFF14;}\n",
".cython.score-115 {background-color: #FFFF14;}\n",
".cython.score-116 {background-color: #FFFF14;}\n",
".cython.score-117 {background-color: #FFFF14;}\n",
".cython.score-118 {background-color: #FFFF13;}\n",
".cython.score-119 {background-color: #FFFF13;}\n",
".cython.score-120 {background-color: #FFFF13;}\n",
".cython.score-121 {background-color: #FFFF13;}\n",
".cython.score-122 {background-color: #FFFF13;}\n",
".cython.score-123 {background-color: #FFFF13;}\n",
".cython.score-124 {background-color: #FFFF13;}\n",
".cython.score-125 {background-color: #FFFF12;}\n",
".cython.score-126 {background-color: #FFFF12;}\n",
".cython.score-127 {background-color: #FFFF12;}\n",
".cython.score-128 {background-color: #FFFF12;}\n",
".cython.score-129 {background-color: #FFFF12;}\n",
".cython.score-130 {background-color: #FFFF12;}\n",
".cython.score-131 {background-color: #FFFF12;}\n",
".cython.score-132 {background-color: #FFFF11;}\n",
".cython.score-133 {background-color: #FFFF11;}\n",
".cython.score-134 {background-color: #FFFF11;}\n",
".cython.score-135 {background-color: #FFFF11;}\n",
".cython.score-136 {background-color: #FFFF11;}\n",
".cython.score-137 {background-color: #FFFF11;}\n",
".cython.score-138 {background-color: #FFFF11;}\n",
".cython.score-139 {background-color: #FFFF11;}\n",
".cython.score-140 {background-color: #FFFF11;}\n",
".cython.score-141 {background-color: #FFFF10;}\n",
".cython.score-142 {background-color: #FFFF10;}\n",
".cython.score-143 {background-color: #FFFF10;}\n",
".cython.score-144 {background-color: #FFFF10;}\n",
".cython.score-145 {background-color: #FFFF10;}\n",
".cython.score-146 {background-color: #FFFF10;}\n",
".cython.score-147 {background-color: #FFFF10;}\n",
".cython.score-148 {background-color: #FFFF10;}\n",
".cython.score-149 {background-color: #FFFF10;}\n",
".cython.score-150 {background-color: #FFFF0f;}\n",
".cython.score-151 {background-color: #FFFF0f;}\n",
".cython.score-152 {background-color: #FFFF0f;}\n",
".cython.score-153 {background-color: #FFFF0f;}\n",
".cython.score-154 {background-color: #FFFF0f;}\n",
".cython.score-155 {background-color: #FFFF0f;}\n",
".cython.score-156 {background-color: #FFFF0f;}\n",
".cython.score-157 {background-color: #FFFF0f;}\n",
".cython.score-158 {background-color: #FFFF0f;}\n",
".cython.score-159 {background-color: #FFFF0f;}\n",
".cython.score-160 {background-color: #FFFF0f;}\n",
".cython.score-161 {background-color: #FFFF0e;}\n",
".cython.score-162 {background-color: #FFFF0e;}\n",
".cython.score-163 {background-color: #FFFF0e;}\n",
".cython.score-164 {background-color: #FFFF0e;}\n",
".cython.score-165 {background-color: #FFFF0e;}\n",
".cython.score-166 {background-color: #FFFF0e;}\n",
".cython.score-167 {background-color: #FFFF0e;}\n",
".cython.score-168 {background-color: #FFFF0e;}\n",
".cython.score-169 {background-color: #FFFF0e;}\n",
".cython.score-170 {background-color: #FFFF0e;}\n",
".cython.score-171 {background-color: #FFFF0e;}\n",
".cython.score-172 {background-color: #FFFF0e;}\n",
".cython.score-173 {background-color: #FFFF0d;}\n",
".cython.score-174 {background-color: #FFFF0d;}\n",
".cython.score-175 {background-color: #FFFF0d;}\n",
".cython.score-176 {background-color: #FFFF0d;}\n",
".cython.score-177 {background-color: #FFFF0d;}\n",
".cython.score-178 {background-color: #FFFF0d;}\n",
".cython.score-179 {background-color: #FFFF0d;}\n",
".cython.score-180 {background-color: #FFFF0d;}\n",
".cython.score-181 {background-color: #FFFF0d;}\n",
".cython.score-182 {background-color: #FFFF0d;}\n",
".cython.score-183 {background-color: #FFFF0d;}\n",
".cython.score-184 {background-color: #FFFF0d;}\n",
".cython.score-185 {background-color: #FFFF0d;}\n",
".cython.score-186 {background-color: #FFFF0d;}\n",
".cython.score-187 {background-color: #FFFF0c;}\n",
".cython.score-188 {background-color: #FFFF0c;}\n",
".cython.score-189 {background-color: #FFFF0c;}\n",
".cython.score-190 {background-color: #FFFF0c;}\n",
".cython.score-191 {background-color: #FFFF0c;}\n",
".cython.score-192 {background-color: #FFFF0c;}\n",
".cython.score-193 {background-color: #FFFF0c;}\n",
".cython.score-194 {background-color: #FFFF0c;}\n",
".cython.score-195 {background-color: #FFFF0c;}\n",
".cython.score-196 {background-color: #FFFF0c;}\n",
".cython.score-197 {background-color: #FFFF0c;}\n",
".cython.score-198 {background-color: #FFFF0c;}\n",
".cython.score-199 {background-color: #FFFF0c;}\n",
".cython.score-200 {background-color: #FFFF0c;}\n",
".cython.score-201 {background-color: #FFFF0c;}\n",
".cython.score-202 {background-color: #FFFF0c;}\n",
".cython.score-203 {background-color: #FFFF0b;}\n",
".cython.score-204 {background-color: #FFFF0b;}\n",
".cython.score-205 {background-color: #FFFF0b;}\n",
".cython.score-206 {background-color: #FFFF0b;}\n",
".cython.score-207 {background-color: #FFFF0b;}\n",
".cython.score-208 {background-color: #FFFF0b;}\n",
".cython.score-209 {background-color: #FFFF0b;}\n",
".cython.score-210 {background-color: #FFFF0b;}\n",
".cython.score-211 {background-color: #FFFF0b;}\n",
".cython.score-212 {background-color: #FFFF0b;}\n",
".cython.score-213 {background-color: #FFFF0b;}\n",
".cython.score-214 {background-color: #FFFF0b;}\n",
".cython.score-215 {background-color: #FFFF0b;}\n",
".cython.score-216 {background-color: #FFFF0b;}\n",
".cython.score-217 {background-color: #FFFF0b;}\n",
".cython.score-218 {background-color: #FFFF0b;}\n",
".cython.score-219 {background-color: #FFFF0b;}\n",
".cython.score-220 {background-color: #FFFF0b;}\n",
".cython.score-221 {background-color: #FFFF0b;}\n",
".cython.score-222 {background-color: #FFFF0a;}\n",
".cython.score-223 {background-color: #FFFF0a;}\n",
".cython.score-224 {background-color: #FFFF0a;}\n",
".cython.score-225 {background-color: #FFFF0a;}\n",
".cython.score-226 {background-color: #FFFF0a;}\n",
".cython.score-227 {background-color: #FFFF0a;}\n",
".cython.score-228 {background-color: #FFFF0a;}\n",
".cython.score-229 {background-color: #FFFF0a;}\n",
".cython.score-230 {background-color: #FFFF0a;}\n",
".cython.score-231 {background-color: #FFFF0a;}\n",
".cython.score-232 {background-color: #FFFF0a;}\n",
".cython.score-233 {background-color: #FFFF0a;}\n",
".cython.score-234 {background-color: #FFFF0a;}\n",
".cython.score-235 {background-color: #FFFF0a;}\n",
".cython.score-236 {background-color: #FFFF0a;}\n",
".cython.score-237 {background-color: #FFFF0a;}\n",
".cython.score-238 {background-color: #FFFF0a;}\n",
".cython.score-239 {background-color: #FFFF0a;}\n",
".cython.score-240 {background-color: #FFFF0a;}\n",
".cython.score-241 {background-color: #FFFF0a;}\n",
".cython.score-242 {background-color: #FFFF0a;}\n",
".cython.score-243 {background-color: #FFFF0a;}\n",
".cython.score-244 {background-color: #FFFF0a;}\n",
".cython.score-245 {background-color: #FFFF0a;}\n",
".cython.score-246 {background-color: #FFFF09;}\n",
".cython.score-247 {background-color: #FFFF09;}\n",
".cython.score-248 {background-color: #FFFF09;}\n",
".cython.score-249 {background-color: #FFFF09;}\n",
".cython.score-250 {background-color: #FFFF09;}\n",
".cython.score-251 {background-color: #FFFF09;}\n",
".cython.score-252 {background-color: #FFFF09;}\n",
".cython.score-253 {background-color: #FFFF09;}\n",
".cython.score-254 {background-color: #FFFF09;}.cython .hll { background-color: #ffffcc }\n",
".cython { background: #f8f8f8; }\n",
".cython .c { color: #408080; font-style: italic } /* Comment */\n",
".cython .err { border: 1px solid #FF0000 } /* Error */\n",
".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
".cython .o { color: #666666 } /* Operator */\n",
".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
".cython .ge { font-style: italic } /* Generic.Emph */\n",
".cython .gr { color: #FF0000 } /* Generic.Error */\n",
".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
".cython .go { color: #888888 } /* Generic.Output */\n",
".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
".cython .gs { font-weight: bold } /* Generic.Strong */\n",
".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
".cython .kt { color: #B00040 } /* Keyword.Type */\n",
".cython .m { color: #666666 } /* Literal.Number */\n",
".cython .s { color: #BA2121 } /* Literal.String */\n",
".cython .na { color: #7D9029 } /* Name.Attribute */\n",
".cython .nb { color: #008000 } /* Name.Builtin */\n",
".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
".cython .no { color: #880000 } /* Name.Constant */\n",
".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
".cython .nf { color: #0000FF } /* Name.Function */\n",
".cython .nl { color: #A0A000 } /* Name.Label */\n",
".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
".cython .nv { color: #19177C } /* Name.Variable */\n",
".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
".cython .sx { color: #008000 } /* Literal.String.Other */\n",
".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
" </style>\n",
" <script>\n",
" function toggleDiv(id) {\n",
" theDiv = id.nextElementSibling\n",
" if (theDiv.style.display != 'block') theDiv.style.display = 'block';\n",
" else theDiv.style.display = 'none';\n",
" }\n",
" </script>\n",
"</head>\n",
"<body class=\"cython\">\n",
"<p>Generated by Cython 0.22</p>\n",
"<div class=\"cython\"><pre class='cython line score-11' onclick='toggleDiv(this)'>+01: <span class=\"k\">import</span> <span class=\"nn\">cython</span></pre>\n",
"<pre class='cython code score-11'> __pyx_t_1 = <span class='py_c_api'>PyDict_New</span>();<span class='error_goto'> if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_test, __pyx_t_1) &lt; 0) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
"</pre><pre class='cython line score-0'>&#xA0;02: </pre>\n",
"<pre class='cython line score-0'>&#xA0;03: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">boundscheck</span><span class=\"p\">(</span><span class=\"bp\">False</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython line score-48' onclick='toggleDiv(this)'>+04: <span class=\"k\">def</span> <span class=\"nf\">slope_cython2</span><span class=\"p\">(</span><span class=\"n\">double</span> <span class=\"p\">[:,</span> <span class=\"p\">:]</span> <span class=\"n\">indata</span><span class=\"p\">,</span> <span class=\"n\">double</span> <span class=\"p\">[:,</span> <span class=\"p\">:]</span> <span class=\"n\">outdata</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-48'>/* Python wrapper */\n",
"static PyObject *__pyx_pw_46_cython_magic_d03f43061db8af8048b429d394d8ec3a_1slope_cython2(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
"static PyMethodDef __pyx_mdef_46_cython_magic_d03f43061db8af8048b429d394d8ec3a_1slope_cython2 = {\"slope_cython2\", (PyCFunction)__pyx_pw_46_cython_magic_d03f43061db8af8048b429d394d8ec3a_1slope_cython2, METH_VARARGS|METH_KEYWORDS, 0};\n",
"static PyObject *__pyx_pw_46_cython_magic_d03f43061db8af8048b429d394d8ec3a_1slope_cython2(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
" __Pyx_memviewslice __pyx_v_indata = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" __Pyx_memviewslice __pyx_v_outdata = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" PyObject *__pyx_r = 0;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"slope_cython2 (wrapper)\", 0);\n",
" {\n",
" static PyObject **__pyx_pyargnames[] = {&amp;__pyx_n_s_indata,&amp;__pyx_n_s_outdata,0};\n",
" PyObject* values[2] = {0,0};\n",
" if (unlikely(__pyx_kwds)) {\n",
" Py_ssize_t kw_args;\n",
" const Py_ssize_t pos_args = <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args);\n",
" switch (pos_args) {\n",
" case 2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" case 1: values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" case 0: break;\n",
" default: goto __pyx_L5_argtuple_error;\n",
" }\n",
" kw_args = <span class='py_c_api'>PyDict_Size</span>(__pyx_kwds);\n",
" switch (pos_args) {\n",
" case 0:\n",
" if (likely((values[0] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_indata)) != 0)) kw_args--;\n",
" else goto __pyx_L5_argtuple_error;\n",
" case 1:\n",
" if (likely((values[1] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_outdata)) != 0)) kw_args--;\n",
" else {\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"slope_cython2\", 1, 2, 2, 1); <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" }\n",
" }\n",
" if (unlikely(kw_args &gt; 0)) {\n",
" if (unlikely(<span class='pyx_c_api'>__Pyx_ParseOptionalKeywords</span>(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"slope_cython2\") &lt; 0)) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" }\n",
" } else if (<span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args) != 2) {\n",
" goto __pyx_L5_argtuple_error;\n",
" } else {\n",
" values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" }\n",
" __pyx_v_indata = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_dsds_double</span>(values[0]);<span class='error_goto'> if (unlikely(!__pyx_v_indata.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" __pyx_v_outdata = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_dsds_double</span>(values[1]);<span class='error_goto'> if (unlikely(!__pyx_v_outdata.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" }\n",
" goto __pyx_L4_argument_unpacking_done;\n",
" __pyx_L5_argtuple_error:;\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"slope_cython2\", 1, 2, 2, <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)); <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" __pyx_L3_error:;\n",
" <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_d03f43061db8af8048b429d394d8ec3a.slope_cython2\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
" <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
" return NULL;\n",
" __pyx_L4_argument_unpacking_done:;\n",
" __pyx_r = __pyx_pf_46_cython_magic_d03f43061db8af8048b429d394d8ec3a_slope_cython2(__pyx_self, __pyx_v_indata, __pyx_v_outdata);\n",
" int __pyx_lineno = 0;\n",
" const char *__pyx_filename = NULL;\n",
" int __pyx_clineno = 0;\n",
"\n",
" /* function exit code */\n",
" <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
" return __pyx_r;\n",
"}\n",
"\n",
"static PyObject *__pyx_pf_46_cython_magic_d03f43061db8af8048b429d394d8ec3a_slope_cython2(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_indata, __Pyx_memviewslice __pyx_v_outdata) {\n",
" int __pyx_v_I;\n",
" int __pyx_v_J;\n",
" int __pyx_v_i;\n",
" int __pyx_v_j;\n",
" double __pyx_v_k;\n",
" double __pyx_v_slp;\n",
" double __pyx_v_dzdx;\n",
" double __pyx_v_dzdy;\n",
" PyObject *__pyx_r = NULL;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"slope_cython2\", 0);\n",
"/* … */\n",
" /* function exit code */\n",
" __pyx_r = Py_None; <span class='pyx_macro_api'>__Pyx_INCREF</span>(Py_None);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_v_indata, 1);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_v_outdata, 1);\n",
" <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
" <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
" return __pyx_r;\n",
"}\n",
"/* … */\n",
" __pyx_tuple__13 = <span class='py_c_api'>PyTuple_Pack</span>(11, __pyx_n_s_indata, __pyx_n_s_outdata, __pyx_n_s_I, __pyx_n_s_J, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_x, __pyx_n_s_k, __pyx_n_s_slp, __pyx_n_s_dzdx, __pyx_n_s_dzdy);<span class='error_goto'> if (unlikely(!__pyx_tuple__13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__13);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__13);\n",
"/* … */\n",
" __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_d03f43061db8af8048b429d394d8ec3a_1slope_cython2, NULL, __pyx_n_s_cython_magic_d03f43061db8af8048);<span class='error_goto'> if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_slope_cython2, __pyx_t_1) &lt; 0) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_codeobj__14 = (PyObject*)<span class='pyx_c_api'>__Pyx_PyCode_New</span>(2, 0, 11, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__13, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_vagrant_cache_ipython_cyth, __pyx_n_s_slope_cython2, 4, __pyx_empty_bytes);<span class='error_goto'> if (unlikely(!__pyx_codeobj__14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
"</pre><pre class='cython line score-0'>&#xA0;05: <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">I</span><span class=\"p\">,</span> <span class=\"nf\">J</span></pre>\n",
"<pre class='cython line score-0'>&#xA0;06: <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span><span class=\"p\">,</span> <span class=\"nf\">j</span><span class=\"p\">,</span> <span class=\"nf\">x</span></pre>\n",
"<pre class='cython line score-0'>&#xA0;07: <span class=\"k\">cdef</span> <span class=\"kt\">double</span> <span class=\"nf\">k</span><span class=\"p\">,</span> <span class=\"nf\">slp</span><span class=\"p\">,</span> <span class=\"nf\">dzdx</span><span class=\"p\">,</span> <span class=\"nf\">dzdy</span></pre>\n",
"<pre class='cython line score-0' onclick='toggleDiv(this)'>+08: <span class=\"n\">I</span> <span class=\"o\">=</span> <span class=\"n\">outdata</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-0'> __pyx_v_I = (__pyx_v_outdata.shape[0]);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+09: <span class=\"n\">J</span> <span class=\"o\">=</span> <span class=\"n\">outdata</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">1</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-0'> __pyx_v_J = (__pyx_v_outdata.shape[1]);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+10: <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">I</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_1 = __pyx_v_I;\n",
" for (__pyx_t_2 = 0; __pyx_t_2 &lt; __pyx_t_1; __pyx_t_2+=1) {\n",
" __pyx_v_i = __pyx_t_2;\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+11: <span class=\"k\">for</span> <span class=\"n\">j</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">J</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_3 = __pyx_v_J;\n",
" for (__pyx_t_4 = 0; __pyx_t_4 &lt; __pyx_t_3; __pyx_t_4+=1) {\n",
" __pyx_v_j = __pyx_t_4;\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+12: <span class=\"n\">dzdx</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"p\">]</span> <span class=\"o\">-</span> <span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"o\">+</span><span class=\"mf\">2</span><span class=\"p\">])</span> <span class=\"o\">/</span> <span class=\"mf\">2</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_5 = (__pyx_v_i + 1);\n",
" __pyx_t_6 = __pyx_v_j;\n",
" if (__pyx_t_5 &lt; 0) __pyx_t_5 += __pyx_v_indata.shape[0];\n",
" if (__pyx_t_6 &lt; 0) __pyx_t_6 += __pyx_v_indata.shape[1];\n",
" __pyx_t_7 = (__pyx_v_i + 1);\n",
" __pyx_t_8 = (__pyx_v_j + 2);\n",
" if (__pyx_t_7 &lt; 0) __pyx_t_7 += __pyx_v_indata.shape[0];\n",
" if (__pyx_t_8 &lt; 0) __pyx_t_8 += __pyx_v_indata.shape[1];\n",
" __pyx_v_dzdx = (((*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_indata.data + __pyx_t_5 * __pyx_v_indata.strides[0]) ) + __pyx_t_6 * __pyx_v_indata.strides[1]) ))) - (*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_indata.data + __pyx_t_7 * __pyx_v_indata.strides[0]) ) + __pyx_t_8 * __pyx_v_indata.strides[1]) )))) / 2.0);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+13: <span class=\"n\">dzdy</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"o\">-</span> <span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">2</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">])</span> <span class=\"o\">/</span> <span class=\"mf\">2</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_9 = __pyx_v_i;\n",
" __pyx_t_10 = (__pyx_v_j + 1);\n",
" if (__pyx_t_9 &lt; 0) __pyx_t_9 += __pyx_v_indata.shape[0];\n",
" if (__pyx_t_10 &lt; 0) __pyx_t_10 += __pyx_v_indata.shape[1];\n",
" __pyx_t_11 = (__pyx_v_i + 2);\n",
" __pyx_t_12 = (__pyx_v_j + 1);\n",
" if (__pyx_t_11 &lt; 0) __pyx_t_11 += __pyx_v_indata.shape[0];\n",
" if (__pyx_t_12 &lt; 0) __pyx_t_12 += __pyx_v_indata.shape[1];\n",
" __pyx_v_dzdy = (((*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_indata.data + __pyx_t_9 * __pyx_v_indata.strides[0]) ) + __pyx_t_10 * __pyx_v_indata.strides[1]) ))) - (*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_indata.data + __pyx_t_11 * __pyx_v_indata.strides[0]) ) + __pyx_t_12 * __pyx_v_indata.strides[1]) )))) / 2.0);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+14: <span class=\"n\">k</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">dzdx</span> <span class=\"o\">*</span> <span class=\"n\">dzdx</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"p\">(</span><span class=\"n\">dzdy</span> <span class=\"o\">*</span> <span class=\"n\">dzdy</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython code score-0'> __pyx_v_k = ((__pyx_v_dzdx * __pyx_v_dzdx) + (__pyx_v_dzdy * __pyx_v_dzdy));\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+15: <span class=\"n\">slp</span> <span class=\"o\">=</span> <span class=\"n\">k</span><span class=\"o\">**</span><span class=\"mf\">0.5</span> <span class=\"o\">*</span> <span class=\"mf\">100</span></pre>\n",
"<pre class='cython code score-0'> __pyx_v_slp = (pow(__pyx_v_k, 0.5) * 100.0);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+16: <span class=\"n\">outdata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">slp</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_13 = __pyx_v_i;\n",
" __pyx_t_14 = __pyx_v_j;\n",
" if (__pyx_t_13 &lt; 0) __pyx_t_13 += __pyx_v_outdata.shape[0];\n",
" if (__pyx_t_14 &lt; 0) __pyx_t_14 += __pyx_v_outdata.shape[1];\n",
" *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_outdata.data + __pyx_t_13 * __pyx_v_outdata.strides[0]) ) + __pyx_t_14 * __pyx_v_outdata.strides[1]) )) = __pyx_v_slp;\n",
" }\n",
" }\n",
"</pre></div></body></html>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%cython -a\n",
"import cython\n",
"\n",
"@cython.boundscheck(False)\n",
"def slope_cython2(double [:, :] indata, double [:, :] outdata):\n",
" cdef int I, J\n",
" cdef int i, j, x\n",
" cdef double k, slp, dzdx, dzdy\n",
" I = outdata.shape[0]\n",
" J = outdata.shape[1]\n",
" for i in range(I):\n",
" for j in range(J):\n",
" dzdx = (indata[i+1, j] - indata[i+1, j+2]) / 2\n",
" dzdy = (indata[i, j+1] - indata[i+2, j+1]) / 2\n",
" k = (dzdx * dzdx) + (dzdy * dzdy)\n",
" slp = k**0.5 * 100\n",
" outdata[i, j] = slp"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"No yellow in the function body, that's what we like to see. The only Python interpreter call this function will invoke is the definition of the function itself. The speed advantage is significant:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"10 loops, best of 3: 149 ms per loop\n"
]
}
],
"source": [
"reset_outdata()\n",
"%timeit slope_cython2(indata, outdata)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From ~8 seconds to 150 *milliseconds*, a speedup of more than 50x. And that's pretty good, but we're still only using a single CPU because of python's [Global Interpretter Lock (GIL)](http://stackoverflow.com/questions/1294382/what-is-a-global-interpreter-lock-gil). Let's use all those cores..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Cython with openmpi"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Cython supports [parallel processing](http://docs.cython.org/src/userguide/parallelism.html) using the OpenMP backend. What does that look like?\n",
"\n",
"First of all, we have to add some extra compile args to link our code to openmp. Next we put the looping in a `nogil` context which releases the GIL restriction (something we can only safely do when our code is in pure C without any interaction with Python objects). Also in the same context block is `parallel` which sets up the openmpi threading. Finally we see `prange`, parallel range, which executes the loop in parallel across the number of cores specified."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false,
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"<!DOCTYPE html>\n",
"<!-- Generated by Cython 0.22 -->\n",
"<html>\n",
"<head>\n",
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
" <style type=\"text/css\">\n",
" \n",
"body.cython { font-family: courier; font-size: 12; }\n",
"\n",
".cython.tag { }\n",
".cython.line { margin: 0em }\n",
".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 20px; }\n",
"\n",
".cython.code .py_c_api { color: red; }\n",
".cython.code .py_macro_api { color: #FF7000; }\n",
".cython.code .pyx_c_api { color: #FF3000; }\n",
".cython.code .pyx_macro_api { color: #FF7000; }\n",
".cython.code .refnanny { color: #FFA000; }\n",
".cython.code .error_goto { color: #FFA000; }\n",
"\n",
".cython.code .coerce { color: #008000; border: 1px dotted #008000 }\n",
".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
".cython.code .c_attr { color: #0000FF; }\n",
".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
".cython.code .c_call { color: #0000FF; }\n",
"\n",
".cython.score-0 {background-color: #FFFFff;}\n",
".cython.score-1 {background-color: #FFFFe7;}\n",
".cython.score-2 {background-color: #FFFFd4;}\n",
".cython.score-3 {background-color: #FFFFc4;}\n",
".cython.score-4 {background-color: #FFFFb6;}\n",
".cython.score-5 {background-color: #FFFFaa;}\n",
".cython.score-6 {background-color: #FFFF9f;}\n",
".cython.score-7 {background-color: #FFFF96;}\n",
".cython.score-8 {background-color: #FFFF8d;}\n",
".cython.score-9 {background-color: #FFFF86;}\n",
".cython.score-10 {background-color: #FFFF7f;}\n",
".cython.score-11 {background-color: #FFFF79;}\n",
".cython.score-12 {background-color: #FFFF73;}\n",
".cython.score-13 {background-color: #FFFF6e;}\n",
".cython.score-14 {background-color: #FFFF6a;}\n",
".cython.score-15 {background-color: #FFFF66;}\n",
".cython.score-16 {background-color: #FFFF62;}\n",
".cython.score-17 {background-color: #FFFF5e;}\n",
".cython.score-18 {background-color: #FFFF5b;}\n",
".cython.score-19 {background-color: #FFFF57;}\n",
".cython.score-20 {background-color: #FFFF55;}\n",
".cython.score-21 {background-color: #FFFF52;}\n",
".cython.score-22 {background-color: #FFFF4f;}\n",
".cython.score-23 {background-color: #FFFF4d;}\n",
".cython.score-24 {background-color: #FFFF4b;}\n",
".cython.score-25 {background-color: #FFFF48;}\n",
".cython.score-26 {background-color: #FFFF46;}\n",
".cython.score-27 {background-color: #FFFF44;}\n",
".cython.score-28 {background-color: #FFFF43;}\n",
".cython.score-29 {background-color: #FFFF41;}\n",
".cython.score-30 {background-color: #FFFF3f;}\n",
".cython.score-31 {background-color: #FFFF3e;}\n",
".cython.score-32 {background-color: #FFFF3c;}\n",
".cython.score-33 {background-color: #FFFF3b;}\n",
".cython.score-34 {background-color: #FFFF39;}\n",
".cython.score-35 {background-color: #FFFF38;}\n",
".cython.score-36 {background-color: #FFFF37;}\n",
".cython.score-37 {background-color: #FFFF36;}\n",
".cython.score-38 {background-color: #FFFF35;}\n",
".cython.score-39 {background-color: #FFFF34;}\n",
".cython.score-40 {background-color: #FFFF33;}\n",
".cython.score-41 {background-color: #FFFF32;}\n",
".cython.score-42 {background-color: #FFFF31;}\n",
".cython.score-43 {background-color: #FFFF30;}\n",
".cython.score-44 {background-color: #FFFF2f;}\n",
".cython.score-45 {background-color: #FFFF2e;}\n",
".cython.score-46 {background-color: #FFFF2d;}\n",
".cython.score-47 {background-color: #FFFF2c;}\n",
".cython.score-48 {background-color: #FFFF2b;}\n",
".cython.score-49 {background-color: #FFFF2b;}\n",
".cython.score-50 {background-color: #FFFF2a;}\n",
".cython.score-51 {background-color: #FFFF29;}\n",
".cython.score-52 {background-color: #FFFF29;}\n",
".cython.score-53 {background-color: #FFFF28;}\n",
".cython.score-54 {background-color: #FFFF27;}\n",
".cython.score-55 {background-color: #FFFF27;}\n",
".cython.score-56 {background-color: #FFFF26;}\n",
".cython.score-57 {background-color: #FFFF26;}\n",
".cython.score-58 {background-color: #FFFF25;}\n",
".cython.score-59 {background-color: #FFFF24;}\n",
".cython.score-60 {background-color: #FFFF24;}\n",
".cython.score-61 {background-color: #FFFF23;}\n",
".cython.score-62 {background-color: #FFFF23;}\n",
".cython.score-63 {background-color: #FFFF22;}\n",
".cython.score-64 {background-color: #FFFF22;}\n",
".cython.score-65 {background-color: #FFFF22;}\n",
".cython.score-66 {background-color: #FFFF21;}\n",
".cython.score-67 {background-color: #FFFF21;}\n",
".cython.score-68 {background-color: #FFFF20;}\n",
".cython.score-69 {background-color: #FFFF20;}\n",
".cython.score-70 {background-color: #FFFF1f;}\n",
".cython.score-71 {background-color: #FFFF1f;}\n",
".cython.score-72 {background-color: #FFFF1f;}\n",
".cython.score-73 {background-color: #FFFF1e;}\n",
".cython.score-74 {background-color: #FFFF1e;}\n",
".cython.score-75 {background-color: #FFFF1e;}\n",
".cython.score-76 {background-color: #FFFF1d;}\n",
".cython.score-77 {background-color: #FFFF1d;}\n",
".cython.score-78 {background-color: #FFFF1c;}\n",
".cython.score-79 {background-color: #FFFF1c;}\n",
".cython.score-80 {background-color: #FFFF1c;}\n",
".cython.score-81 {background-color: #FFFF1c;}\n",
".cython.score-82 {background-color: #FFFF1b;}\n",
".cython.score-83 {background-color: #FFFF1b;}\n",
".cython.score-84 {background-color: #FFFF1b;}\n",
".cython.score-85 {background-color: #FFFF1a;}\n",
".cython.score-86 {background-color: #FFFF1a;}\n",
".cython.score-87 {background-color: #FFFF1a;}\n",
".cython.score-88 {background-color: #FFFF1a;}\n",
".cython.score-89 {background-color: #FFFF19;}\n",
".cython.score-90 {background-color: #FFFF19;}\n",
".cython.score-91 {background-color: #FFFF19;}\n",
".cython.score-92 {background-color: #FFFF19;}\n",
".cython.score-93 {background-color: #FFFF18;}\n",
".cython.score-94 {background-color: #FFFF18;}\n",
".cython.score-95 {background-color: #FFFF18;}\n",
".cython.score-96 {background-color: #FFFF18;}\n",
".cython.score-97 {background-color: #FFFF17;}\n",
".cython.score-98 {background-color: #FFFF17;}\n",
".cython.score-99 {background-color: #FFFF17;}\n",
".cython.score-100 {background-color: #FFFF17;}\n",
".cython.score-101 {background-color: #FFFF16;}\n",
".cython.score-102 {background-color: #FFFF16;}\n",
".cython.score-103 {background-color: #FFFF16;}\n",
".cython.score-104 {background-color: #FFFF16;}\n",
".cython.score-105 {background-color: #FFFF16;}\n",
".cython.score-106 {background-color: #FFFF15;}\n",
".cython.score-107 {background-color: #FFFF15;}\n",
".cython.score-108 {background-color: #FFFF15;}\n",
".cython.score-109 {background-color: #FFFF15;}\n",
".cython.score-110 {background-color: #FFFF15;}\n",
".cython.score-111 {background-color: #FFFF15;}\n",
".cython.score-112 {background-color: #FFFF14;}\n",
".cython.score-113 {background-color: #FFFF14;}\n",
".cython.score-114 {background-color: #FFFF14;}\n",
".cython.score-115 {background-color: #FFFF14;}\n",
".cython.score-116 {background-color: #FFFF14;}\n",
".cython.score-117 {background-color: #FFFF14;}\n",
".cython.score-118 {background-color: #FFFF13;}\n",
".cython.score-119 {background-color: #FFFF13;}\n",
".cython.score-120 {background-color: #FFFF13;}\n",
".cython.score-121 {background-color: #FFFF13;}\n",
".cython.score-122 {background-color: #FFFF13;}\n",
".cython.score-123 {background-color: #FFFF13;}\n",
".cython.score-124 {background-color: #FFFF13;}\n",
".cython.score-125 {background-color: #FFFF12;}\n",
".cython.score-126 {background-color: #FFFF12;}\n",
".cython.score-127 {background-color: #FFFF12;}\n",
".cython.score-128 {background-color: #FFFF12;}\n",
".cython.score-129 {background-color: #FFFF12;}\n",
".cython.score-130 {background-color: #FFFF12;}\n",
".cython.score-131 {background-color: #FFFF12;}\n",
".cython.score-132 {background-color: #FFFF11;}\n",
".cython.score-133 {background-color: #FFFF11;}\n",
".cython.score-134 {background-color: #FFFF11;}\n",
".cython.score-135 {background-color: #FFFF11;}\n",
".cython.score-136 {background-color: #FFFF11;}\n",
".cython.score-137 {background-color: #FFFF11;}\n",
".cython.score-138 {background-color: #FFFF11;}\n",
".cython.score-139 {background-color: #FFFF11;}\n",
".cython.score-140 {background-color: #FFFF11;}\n",
".cython.score-141 {background-color: #FFFF10;}\n",
".cython.score-142 {background-color: #FFFF10;}\n",
".cython.score-143 {background-color: #FFFF10;}\n",
".cython.score-144 {background-color: #FFFF10;}\n",
".cython.score-145 {background-color: #FFFF10;}\n",
".cython.score-146 {background-color: #FFFF10;}\n",
".cython.score-147 {background-color: #FFFF10;}\n",
".cython.score-148 {background-color: #FFFF10;}\n",
".cython.score-149 {background-color: #FFFF10;}\n",
".cython.score-150 {background-color: #FFFF0f;}\n",
".cython.score-151 {background-color: #FFFF0f;}\n",
".cython.score-152 {background-color: #FFFF0f;}\n",
".cython.score-153 {background-color: #FFFF0f;}\n",
".cython.score-154 {background-color: #FFFF0f;}\n",
".cython.score-155 {background-color: #FFFF0f;}\n",
".cython.score-156 {background-color: #FFFF0f;}\n",
".cython.score-157 {background-color: #FFFF0f;}\n",
".cython.score-158 {background-color: #FFFF0f;}\n",
".cython.score-159 {background-color: #FFFF0f;}\n",
".cython.score-160 {background-color: #FFFF0f;}\n",
".cython.score-161 {background-color: #FFFF0e;}\n",
".cython.score-162 {background-color: #FFFF0e;}\n",
".cython.score-163 {background-color: #FFFF0e;}\n",
".cython.score-164 {background-color: #FFFF0e;}\n",
".cython.score-165 {background-color: #FFFF0e;}\n",
".cython.score-166 {background-color: #FFFF0e;}\n",
".cython.score-167 {background-color: #FFFF0e;}\n",
".cython.score-168 {background-color: #FFFF0e;}\n",
".cython.score-169 {background-color: #FFFF0e;}\n",
".cython.score-170 {background-color: #FFFF0e;}\n",
".cython.score-171 {background-color: #FFFF0e;}\n",
".cython.score-172 {background-color: #FFFF0e;}\n",
".cython.score-173 {background-color: #FFFF0d;}\n",
".cython.score-174 {background-color: #FFFF0d;}\n",
".cython.score-175 {background-color: #FFFF0d;}\n",
".cython.score-176 {background-color: #FFFF0d;}\n",
".cython.score-177 {background-color: #FFFF0d;}\n",
".cython.score-178 {background-color: #FFFF0d;}\n",
".cython.score-179 {background-color: #FFFF0d;}\n",
".cython.score-180 {background-color: #FFFF0d;}\n",
".cython.score-181 {background-color: #FFFF0d;}\n",
".cython.score-182 {background-color: #FFFF0d;}\n",
".cython.score-183 {background-color: #FFFF0d;}\n",
".cython.score-184 {background-color: #FFFF0d;}\n",
".cython.score-185 {background-color: #FFFF0d;}\n",
".cython.score-186 {background-color: #FFFF0d;}\n",
".cython.score-187 {background-color: #FFFF0c;}\n",
".cython.score-188 {background-color: #FFFF0c;}\n",
".cython.score-189 {background-color: #FFFF0c;}\n",
".cython.score-190 {background-color: #FFFF0c;}\n",
".cython.score-191 {background-color: #FFFF0c;}\n",
".cython.score-192 {background-color: #FFFF0c;}\n",
".cython.score-193 {background-color: #FFFF0c;}\n",
".cython.score-194 {background-color: #FFFF0c;}\n",
".cython.score-195 {background-color: #FFFF0c;}\n",
".cython.score-196 {background-color: #FFFF0c;}\n",
".cython.score-197 {background-color: #FFFF0c;}\n",
".cython.score-198 {background-color: #FFFF0c;}\n",
".cython.score-199 {background-color: #FFFF0c;}\n",
".cython.score-200 {background-color: #FFFF0c;}\n",
".cython.score-201 {background-color: #FFFF0c;}\n",
".cython.score-202 {background-color: #FFFF0c;}\n",
".cython.score-203 {background-color: #FFFF0b;}\n",
".cython.score-204 {background-color: #FFFF0b;}\n",
".cython.score-205 {background-color: #FFFF0b;}\n",
".cython.score-206 {background-color: #FFFF0b;}\n",
".cython.score-207 {background-color: #FFFF0b;}\n",
".cython.score-208 {background-color: #FFFF0b;}\n",
".cython.score-209 {background-color: #FFFF0b;}\n",
".cython.score-210 {background-color: #FFFF0b;}\n",
".cython.score-211 {background-color: #FFFF0b;}\n",
".cython.score-212 {background-color: #FFFF0b;}\n",
".cython.score-213 {background-color: #FFFF0b;}\n",
".cython.score-214 {background-color: #FFFF0b;}\n",
".cython.score-215 {background-color: #FFFF0b;}\n",
".cython.score-216 {background-color: #FFFF0b;}\n",
".cython.score-217 {background-color: #FFFF0b;}\n",
".cython.score-218 {background-color: #FFFF0b;}\n",
".cython.score-219 {background-color: #FFFF0b;}\n",
".cython.score-220 {background-color: #FFFF0b;}\n",
".cython.score-221 {background-color: #FFFF0b;}\n",
".cython.score-222 {background-color: #FFFF0a;}\n",
".cython.score-223 {background-color: #FFFF0a;}\n",
".cython.score-224 {background-color: #FFFF0a;}\n",
".cython.score-225 {background-color: #FFFF0a;}\n",
".cython.score-226 {background-color: #FFFF0a;}\n",
".cython.score-227 {background-color: #FFFF0a;}\n",
".cython.score-228 {background-color: #FFFF0a;}\n",
".cython.score-229 {background-color: #FFFF0a;}\n",
".cython.score-230 {background-color: #FFFF0a;}\n",
".cython.score-231 {background-color: #FFFF0a;}\n",
".cython.score-232 {background-color: #FFFF0a;}\n",
".cython.score-233 {background-color: #FFFF0a;}\n",
".cython.score-234 {background-color: #FFFF0a;}\n",
".cython.score-235 {background-color: #FFFF0a;}\n",
".cython.score-236 {background-color: #FFFF0a;}\n",
".cython.score-237 {background-color: #FFFF0a;}\n",
".cython.score-238 {background-color: #FFFF0a;}\n",
".cython.score-239 {background-color: #FFFF0a;}\n",
".cython.score-240 {background-color: #FFFF0a;}\n",
".cython.score-241 {background-color: #FFFF0a;}\n",
".cython.score-242 {background-color: #FFFF0a;}\n",
".cython.score-243 {background-color: #FFFF0a;}\n",
".cython.score-244 {background-color: #FFFF0a;}\n",
".cython.score-245 {background-color: #FFFF0a;}\n",
".cython.score-246 {background-color: #FFFF09;}\n",
".cython.score-247 {background-color: #FFFF09;}\n",
".cython.score-248 {background-color: #FFFF09;}\n",
".cython.score-249 {background-color: #FFFF09;}\n",
".cython.score-250 {background-color: #FFFF09;}\n",
".cython.score-251 {background-color: #FFFF09;}\n",
".cython.score-252 {background-color: #FFFF09;}\n",
".cython.score-253 {background-color: #FFFF09;}\n",
".cython.score-254 {background-color: #FFFF09;}.cython .hll { background-color: #ffffcc }\n",
".cython { background: #f8f8f8; }\n",
".cython .c { color: #408080; font-style: italic } /* Comment */\n",
".cython .err { border: 1px solid #FF0000 } /* Error */\n",
".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
".cython .o { color: #666666 } /* Operator */\n",
".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
".cython .ge { font-style: italic } /* Generic.Emph */\n",
".cython .gr { color: #FF0000 } /* Generic.Error */\n",
".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
".cython .go { color: #888888 } /* Generic.Output */\n",
".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
".cython .gs { font-weight: bold } /* Generic.Strong */\n",
".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
".cython .kt { color: #B00040 } /* Keyword.Type */\n",
".cython .m { color: #666666 } /* Literal.Number */\n",
".cython .s { color: #BA2121 } /* Literal.String */\n",
".cython .na { color: #7D9029 } /* Name.Attribute */\n",
".cython .nb { color: #008000 } /* Name.Builtin */\n",
".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
".cython .no { color: #880000 } /* Name.Constant */\n",
".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
".cython .nf { color: #0000FF } /* Name.Function */\n",
".cython .nl { color: #A0A000 } /* Name.Label */\n",
".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
".cython .nv { color: #19177C } /* Name.Variable */\n",
".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
".cython .sx { color: #008000 } /* Literal.String.Other */\n",
".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
" </style>\n",
" <script>\n",
" function toggleDiv(id) {\n",
" theDiv = id.nextElementSibling\n",
" if (theDiv.style.display != 'block') theDiv.style.display = 'block';\n",
" else theDiv.style.display = 'none';\n",
" }\n",
" </script>\n",
"</head>\n",
"<body class=\"cython\">\n",
"<p>Generated by Cython 0.22</p>\n",
"<div class=\"cython\"><pre class='cython line score-0'>&#xA0;01: </pre>\n",
"<pre class='cython line score-11' onclick='toggleDiv(this)'>+02: <span class=\"k\">import</span> <span class=\"nn\">cython</span></pre>\n",
"<pre class='cython code score-11'> __pyx_t_1 = <span class='py_c_api'>PyDict_New</span>();<span class='error_goto'> if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_test, __pyx_t_1) &lt; 0) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
"</pre><pre class='cython line score-0'>&#xA0;03: <span class=\"k\">from</span> <span class=\"nn\">cython.parallel</span> <span class=\"k\">import</span> <span class=\"n\">prange</span><span class=\"p\">,</span> <span class=\"n\">parallel</span></pre>\n",
"<pre class='cython line score-0'>&#xA0;04: </pre>\n",
"<pre class='cython line score-0'>&#xA0;05: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">boundscheck</span><span class=\"p\">(</span><span class=\"bp\">False</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython line score-48' onclick='toggleDiv(this)'>+06: <span class=\"k\">def</span> <span class=\"nf\">slope_cython_mpi</span><span class=\"p\">(</span><span class=\"n\">double</span> <span class=\"p\">[:,</span> <span class=\"p\">:]</span> <span class=\"n\">indata</span><span class=\"p\">,</span> <span class=\"n\">double</span> <span class=\"p\">[:,</span> <span class=\"p\">:]</span> <span class=\"n\">outdata</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-48'>/* Python wrapper */\n",
"static PyObject *__pyx_pw_46_cython_magic_2e6b712520789537463b24d179fbe62b_1slope_cython_mpi(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
"static PyMethodDef __pyx_mdef_46_cython_magic_2e6b712520789537463b24d179fbe62b_1slope_cython_mpi = {\"slope_cython_mpi\", (PyCFunction)__pyx_pw_46_cython_magic_2e6b712520789537463b24d179fbe62b_1slope_cython_mpi, METH_VARARGS|METH_KEYWORDS, 0};\n",
"static PyObject *__pyx_pw_46_cython_magic_2e6b712520789537463b24d179fbe62b_1slope_cython_mpi(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
" __Pyx_memviewslice __pyx_v_indata = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" __Pyx_memviewslice __pyx_v_outdata = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" PyObject *__pyx_r = 0;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"slope_cython_mpi (wrapper)\", 0);\n",
" {\n",
" static PyObject **__pyx_pyargnames[] = {&amp;__pyx_n_s_indata,&amp;__pyx_n_s_outdata,0};\n",
" PyObject* values[2] = {0,0};\n",
" if (unlikely(__pyx_kwds)) {\n",
" Py_ssize_t kw_args;\n",
" const Py_ssize_t pos_args = <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args);\n",
" switch (pos_args) {\n",
" case 2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" case 1: values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" case 0: break;\n",
" default: goto __pyx_L5_argtuple_error;\n",
" }\n",
" kw_args = <span class='py_c_api'>PyDict_Size</span>(__pyx_kwds);\n",
" switch (pos_args) {\n",
" case 0:\n",
" if (likely((values[0] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_indata)) != 0)) kw_args--;\n",
" else goto __pyx_L5_argtuple_error;\n",
" case 1:\n",
" if (likely((values[1] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_outdata)) != 0)) kw_args--;\n",
" else {\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"slope_cython_mpi\", 1, 2, 2, 1); <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" }\n",
" }\n",
" if (unlikely(kw_args &gt; 0)) {\n",
" if (unlikely(<span class='pyx_c_api'>__Pyx_ParseOptionalKeywords</span>(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"slope_cython_mpi\") &lt; 0)) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" }\n",
" } else if (<span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args) != 2) {\n",
" goto __pyx_L5_argtuple_error;\n",
" } else {\n",
" values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" }\n",
" __pyx_v_indata = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_dsds_double</span>(values[0]);<span class='error_goto'> if (unlikely(!__pyx_v_indata.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" __pyx_v_outdata = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_dsds_double</span>(values[1]);<span class='error_goto'> if (unlikely(!__pyx_v_outdata.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" }\n",
" goto __pyx_L4_argument_unpacking_done;\n",
" __pyx_L5_argtuple_error:;\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"slope_cython_mpi\", 1, 2, 2, <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)); <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}</span>\n",
" __pyx_L3_error:;\n",
" <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_2e6b712520789537463b24d179fbe62b.slope_cython_mpi\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
" <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
" return NULL;\n",
" __pyx_L4_argument_unpacking_done:;\n",
" __pyx_r = __pyx_pf_46_cython_magic_2e6b712520789537463b24d179fbe62b_slope_cython_mpi(__pyx_self, __pyx_v_indata, __pyx_v_outdata);\n",
" int __pyx_lineno = 0;\n",
" const char *__pyx_filename = NULL;\n",
" int __pyx_clineno = 0;\n",
"\n",
" /* function exit code */\n",
" <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
" return __pyx_r;\n",
"}\n",
"\n",
"static PyObject *__pyx_pf_46_cython_magic_2e6b712520789537463b24d179fbe62b_slope_cython_mpi(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_indata, __Pyx_memviewslice __pyx_v_outdata) {\n",
" CYTHON_UNUSED int __pyx_v_I;\n",
" int __pyx_v_J;\n",
" int __pyx_v_i;\n",
" int __pyx_v_j;\n",
" double __pyx_v_k;\n",
" double __pyx_v_slp;\n",
" double __pyx_v_dzdx;\n",
" double __pyx_v_dzdy;\n",
" PyObject *__pyx_r = NULL;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"slope_cython_mpi\", 0);\n",
"/* … */\n",
" /* function exit code */\n",
" __pyx_r = Py_None; <span class='pyx_macro_api'>__Pyx_INCREF</span>(Py_None);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_v_indata, 1);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_v_outdata, 1);\n",
" <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
" <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
" return __pyx_r;\n",
"}\n",
"/* … */\n",
" __pyx_tuple__13 = <span class='py_c_api'>PyTuple_Pack</span>(11, __pyx_n_s_indata, __pyx_n_s_outdata, __pyx_n_s_I, __pyx_n_s_J, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_x, __pyx_n_s_k, __pyx_n_s_slp, __pyx_n_s_dzdx, __pyx_n_s_dzdy);<span class='error_goto'> if (unlikely(!__pyx_tuple__13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__13);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__13);\n",
"/* … */\n",
" __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_2e6b712520789537463b24d179fbe62b_1slope_cython_mpi, NULL, __pyx_n_s_cython_magic_2e6b71252078953746);<span class='error_goto'> if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_slope_cython_mpi, __pyx_t_1) &lt; 0) <span class='error_goto'>{__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_codeobj__14 = (PyObject*)<span class='pyx_c_api'>__Pyx_PyCode_New</span>(2, 0, 11, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__13, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_vagrant_cache_ipython_cyth, __pyx_n_s_slope_cython_mpi, 6, __pyx_empty_bytes);<span class='error_goto'> if (unlikely(!__pyx_codeobj__14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}</span>\n",
"</pre><pre class='cython line score-0'>&#xA0;07: <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">I</span><span class=\"p\">,</span> <span class=\"nf\">J</span></pre>\n",
"<pre class='cython line score-0'>&#xA0;08: <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span><span class=\"p\">,</span> <span class=\"nf\">j</span><span class=\"p\">,</span> <span class=\"nf\">x</span></pre>\n",
"<pre class='cython line score-0'>&#xA0;09: <span class=\"k\">cdef</span> <span class=\"kt\">double</span> <span class=\"nf\">k</span><span class=\"p\">,</span> <span class=\"nf\">slp</span><span class=\"p\">,</span> <span class=\"nf\">dzdx</span><span class=\"p\">,</span> <span class=\"nf\">dzdy</span></pre>\n",
"<pre class='cython line score-0' onclick='toggleDiv(this)'>+10: <span class=\"n\">I</span> <span class=\"o\">=</span> <span class=\"n\">outdata</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-0'> __pyx_v_I = (__pyx_v_outdata.shape[0]);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+11: <span class=\"n\">J</span> <span class=\"o\">=</span> <span class=\"n\">outdata</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">1</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-0'> __pyx_v_J = (__pyx_v_outdata.shape[1]);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+12: <span class=\"k\">with</span> <span class=\"k\">nogil</span><span class=\"p\">,</span> <span class=\"n\">parallel</span><span class=\"p\">(</span><span class=\"n\">num_threads</span><span class=\"o\">=</span><span class=\"mf\">4</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0'> {\n",
" #ifdef WITH_THREAD\n",
" PyThreadState *_save;\n",
" Py_UNBLOCK_THREADS\n",
" #endif\n",
" /*try:*/ {\n",
" {\n",
" #if ((defined(__APPLE__) || defined(__OSX__)) &amp;&amp; (defined(__GNUC__) &amp;&amp; (__GNUC__ &gt; 2 || (__GNUC__ == 2 &amp;&amp; (__GNUC_MINOR__ &gt; 95)))))\n",
" #undef likely\n",
" #undef unlikely\n",
" #define likely(x) (x)\n",
" #define unlikely(x) (x)\n",
" #endif\n",
" #ifdef _OPENMP\n",
" #pragma omp parallel num_threads(4)\n",
" #endif /* _OPENMP */\n",
" {\n",
"/* … */\n",
" /*finally:*/ {\n",
" /*normal exit:*/{\n",
" #ifdef WITH_THREAD\n",
" Py_BLOCK_THREADS\n",
" #endif\n",
" goto __pyx_L5;\n",
" }\n",
" __pyx_L5:;\n",
" }\n",
" }\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+13: <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"n\">prange</span><span class=\"p\">(</span><span class=\"n\">I</span><span class=\"p\">,</span> <span class=\"n\">schedule</span><span class=\"o\">=</span><span class=\"s\">&#39;dynamic&#39;</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_1 = __pyx_v_I;\n",
" if (1 == 0) abort();\n",
" {\n",
" __pyx_t_3 = (__pyx_t_1 - 0) / 1;\n",
" if (__pyx_t_3 &gt; 0)\n",
" {\n",
" #ifdef _OPENMP\n",
" #pragma omp for lastprivate(__pyx_v_dzdx) lastprivate(__pyx_v_dzdy) firstprivate(__pyx_v_i) lastprivate(__pyx_v_i) lastprivate(__pyx_v_j) lastprivate(__pyx_v_slp) lastprivate(__pyx_v_k) schedule(dynamic)\n",
" #endif /* _OPENMP */\n",
" for (__pyx_t_2 = 0; __pyx_t_2 &lt; __pyx_t_3; __pyx_t_2++){\n",
" {\n",
" __pyx_v_i = 0 + 1 * __pyx_t_2;\n",
" /* Initialize private variables to invalid values */\n",
" __pyx_v_dzdx = ((double)__PYX_NAN());\n",
" __pyx_v_dzdy = ((double)__PYX_NAN());\n",
" __pyx_v_j = ((int)0xbad0bad0);\n",
" __pyx_v_slp = ((double)__PYX_NAN());\n",
" __pyx_v_k = ((double)__PYX_NAN());\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+14: <span class=\"k\">for</span> <span class=\"n\">j</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">J</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_4 = __pyx_v_J;\n",
" for (__pyx_t_5 = 0; __pyx_t_5 &lt; __pyx_t_4; __pyx_t_5+=1) {\n",
" __pyx_v_j = __pyx_t_5;\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+15: <span class=\"n\">dzdx</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"p\">]</span> <span class=\"o\">-</span> <span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"o\">+</span><span class=\"mf\">2</span><span class=\"p\">])</span> <span class=\"o\">/</span> <span class=\"mf\">2</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_6 = (__pyx_v_i + 1);\n",
" __pyx_t_7 = __pyx_v_j;\n",
" if (__pyx_t_6 &lt; 0) __pyx_t_6 += __pyx_v_indata.shape[0];\n",
" if (__pyx_t_7 &lt; 0) __pyx_t_7 += __pyx_v_indata.shape[1];\n",
" __pyx_t_8 = (__pyx_v_i + 1);\n",
" __pyx_t_9 = (__pyx_v_j + 2);\n",
" if (__pyx_t_8 &lt; 0) __pyx_t_8 += __pyx_v_indata.shape[0];\n",
" if (__pyx_t_9 &lt; 0) __pyx_t_9 += __pyx_v_indata.shape[1];\n",
" __pyx_v_dzdx = (((*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_indata.data + __pyx_t_6 * __pyx_v_indata.strides[0]) ) + __pyx_t_7 * __pyx_v_indata.strides[1]) ))) - (*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_indata.data + __pyx_t_8 * __pyx_v_indata.strides[0]) ) + __pyx_t_9 * __pyx_v_indata.strides[1]) )))) / 2.0);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+16: <span class=\"n\">dzdy</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"o\">-</span> <span class=\"n\">indata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mf\">2</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"o\">+</span><span class=\"mf\">1</span><span class=\"p\">])</span> <span class=\"o\">/</span> <span class=\"mf\">2</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_10 = __pyx_v_i;\n",
" __pyx_t_11 = (__pyx_v_j + 1);\n",
" if (__pyx_t_10 &lt; 0) __pyx_t_10 += __pyx_v_indata.shape[0];\n",
" if (__pyx_t_11 &lt; 0) __pyx_t_11 += __pyx_v_indata.shape[1];\n",
" __pyx_t_12 = (__pyx_v_i + 2);\n",
" __pyx_t_13 = (__pyx_v_j + 1);\n",
" if (__pyx_t_12 &lt; 0) __pyx_t_12 += __pyx_v_indata.shape[0];\n",
" if (__pyx_t_13 &lt; 0) __pyx_t_13 += __pyx_v_indata.shape[1];\n",
" __pyx_v_dzdy = (((*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_indata.data + __pyx_t_10 * __pyx_v_indata.strides[0]) ) + __pyx_t_11 * __pyx_v_indata.strides[1]) ))) - (*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_indata.data + __pyx_t_12 * __pyx_v_indata.strides[0]) ) + __pyx_t_13 * __pyx_v_indata.strides[1]) )))) / 2.0);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+17: <span class=\"n\">k</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">dzdx</span> <span class=\"o\">*</span> <span class=\"n\">dzdx</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"p\">(</span><span class=\"n\">dzdy</span> <span class=\"o\">*</span> <span class=\"n\">dzdy</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython code score-0'> __pyx_v_k = ((__pyx_v_dzdx * __pyx_v_dzdx) + (__pyx_v_dzdy * __pyx_v_dzdy));\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+18: <span class=\"n\">slp</span> <span class=\"o\">=</span> <span class=\"n\">k</span><span class=\"o\">**</span><span class=\"mf\">0.5</span> <span class=\"o\">*</span> <span class=\"mf\">100</span></pre>\n",
"<pre class='cython code score-0'> __pyx_v_slp = (pow(__pyx_v_k, 0.5) * 100.0);\n",
"</pre><pre class='cython line score-0' onclick='toggleDiv(this)'>+19: <span class=\"n\">outdata</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">j</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">slp</span></pre>\n",
"<pre class='cython code score-0'> __pyx_t_14 = __pyx_v_i;\n",
" __pyx_t_15 = __pyx_v_j;\n",
" if (__pyx_t_14 &lt; 0) __pyx_t_14 += __pyx_v_outdata.shape[0];\n",
" if (__pyx_t_15 &lt; 0) __pyx_t_15 += __pyx_v_outdata.shape[1];\n",
" *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_outdata.data + __pyx_t_14 * __pyx_v_outdata.strides[0]) ) + __pyx_t_15 * __pyx_v_outdata.strides[1]) )) = __pyx_v_slp;\n",
" }\n",
" }\n",
" }\n",
" }\n",
" }\n",
" }\n",
" }\n",
" #if ((defined(__APPLE__) || defined(__OSX__)) &amp;&amp; (defined(__GNUC__) &amp;&amp; (__GNUC__ &gt; 2 || (__GNUC__ == 2 &amp;&amp; (__GNUC_MINOR__ &gt; 95)))))\n",
" #undef likely\n",
" #undef unlikely\n",
" #define likely(x) __builtin_expect(!!(x), 1)\n",
" #define unlikely(x) __builtin_expect(!!(x), 0)\n",
" #endif\n",
" }\n",
"</pre></div></body></html>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%cython --compile-args=-fopenmp --link-args=-fopenmp --force -a\n",
"\n",
"import cython\n",
"from cython.parallel import prange, parallel\n",
"\n",
"@cython.boundscheck(False)\n",
"def slope_cython_mpi(double [:, :] indata, double [:, :] outdata):\n",
" cdef int I, J\n",
" cdef int i, j, x\n",
" cdef double k, slp, dzdx, dzdy\n",
" I = outdata.shape[0]\n",
" J = outdata.shape[1]\n",
" with nogil, parallel(num_threads=4):\n",
" for i in prange(I, schedule='dynamic'):\n",
" for j in range(J):\n",
" dzdx = (indata[i+1, j] - indata[i+1, j+2]) / 2\n",
" dzdy = (indata[i, j+1] - indata[i+2, j+1]) / 2\n",
" k = (dzdx * dzdx) + (dzdy * dzdy)\n",
" slp = k**0.5 * 100\n",
" outdata[i, j] = slp"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"10 loops, best of 3: 41.6 ms per loop\n"
]
}
],
"source": [
"reset_outdata()\n",
"%timeit slope_cython_mpi(indata, outdata)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"42ms for the parallel version down, from 150ms for the single-core version - an *additional* speedup of 3.6x. Since we had 4 threads, 4x would be ideal but parallelism has some overhead. If the computation is sufficiently CPU intensive within that `prange`, the overhead of threading isn't enough to completely dull the benefits of parallelism.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"I was able to make this particular array operation roughly 200x faster using code that looks remarkably similar to the original naive python implementation. Most importantly, the API did not change at all; the speed benefits and parallelism are completely transparent to the user of this function. \n",
"\n",
"If you are processing an array using loops, you should definitely look at Cython, particularly Cython with openmpi parallelism, to speed up your operations.\n",
"\n",
"Questions? Message me on twitter @perrygeo"
]
}
],
"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.4.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment