Skip to content

Instantly share code, notes, and snippets.

@seibert
Created August 25, 2014 17:21
Show Gist options
  • Save seibert/6393bc1011c7bae06225 to your computer and use it in GitHub Desktop.
Save seibert/6393bc1011c7bae06225 to your computer and use it in GitHub Desktop.
NumbaPro Batch FFT Example
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "",
"signature": "sha256:7b1a0687b42c369e7c82a317498d5b50312a2608d2c69b5b78cae44958ebc60b"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "code",
"collapsed": false,
"input": [
"%pylab inline\n",
"import numpy as np\n",
"from numbapro.cudalib import cufft"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Populating the interactive namespace from numpy and matplotlib\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"Vendor: Continuum Analytics, Inc.\n",
"Package: numbapro\n",
"Message: trial mode expires in 30 days\n"
]
}
],
"prompt_number": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Step 1: Construct some input data\n",
"We will compute the FFT for two input arrays at the same time. By using integer frequency multipliers (3 and 7, in this case) over the range $[0, 2\\pi]$, we know what the FFT should look like when we are done."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"n = 100\n",
"x = np.linspace(0, 2*np.pi, n)\n",
"freq1 = np.sin(x * 3)\n",
"freq2 = np.sin(x * 7)\n",
"plot(x, freq1, 'b', x, freq2, 'r')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 2,
"text": [
"[<matplotlib.lines.Line2D at 0x10c085550>,\n",
" <matplotlib.lines.Line2D at 0x10c0857d0>]"
]
},
{
"metadata": {},
"output_type": "display_data",
"png": "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\ngg==\n",
"text": [
"<matplotlib.figure.Figure at 0x10bfac2d0>"
]
}
],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Step 2: Create batch input\n",
"The batched input array will just be the two arrays concatenated. NumbaPro does not currently support the more advanced layouts supported by `cufftPlanMany`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"batch_input = np.concatenate((freq1, freq2))\n",
"batch_input.shape"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 3,
"text": [
"(200,)"
]
}
],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Step 3: Setup CUFFT Plan\n",
"\n",
"NumbaPro supports batch transformations via the `batch` argument to `FFTPlan`. CUFFT requires that real input arrays be transformed to complex output arrays."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"input_shape = freq1.shape # or freq2.shape\n",
"batch_operations = 2 # Two input arrays are concatenated\n",
"plan = cufft.FFTPlan(input_shape, batch_input.dtype, np.complex128, batch_operations)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Step 4: Setup output array\n",
"\n",
"*As of NumbaPro 0.14.3, there is a bug in batched transforms that requires you to pass in an explicit output array of the correct size.*"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"output_size = input_shape[0]//2 + 1\n",
"batch_output = np.zeros(2 * output_size, dtype=np.complex128)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Step 5: Perform transform\n",
"\n",
"Once we execute the FFT, we can slice out the results of the individual transforms from the `batch_output` array."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"_ = plan.forward(batch_input, out=batch_output)\n",
"fft1 = batch_output[:output_size]\n",
"fft2 = batch_output[output_size:]"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Step 6: Inspect results\n",
"\n",
"We can find the index where the maximum power in each FFT is (which nicely maps to our integer frequency) and also plot the absolute value of the FFT."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print('fft1 max freq: %d' % np.argmax(np.abs(fft1)))\n",
"print('fft2 max freq: %d' % np.argmax(np.abs(fft2)))\n",
"plot(np.abs(fft1), 'b', np.abs(fft2), 'r')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"fft1 max freq: 3\n",
"fft2 max freq: 7\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 7,
"text": [
"[<matplotlib.lines.Line2D at 0x114dc4ed0>,\n",
" <matplotlib.lines.Line2D at 0x114dd2190>]"
]
},
{
"metadata": {},
"output_type": "display_data",
"png": "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\n",
"text": [
"<matplotlib.figure.Figure at 0x114d3bf90>"
]
}
],
"prompt_number": 7
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment