{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Embed Futhark in iPython Notebook\n", "\n", "💥💻💥 A data-parallel functional programming language http://futhark-lang.org / http://github.com/hiperfit/futhark\n", "\n", "### Load extension" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%load_ext futhark" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Write futhark code\n", "\n", "* `%%futhark` magic cell\n", "* Add the `gpu` option to compile and run with pyopencl" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Warning: Device limits tile size to 22 (setting was 32)\n" ] } ], "source": [ "%%futhark gpu\n", "\n", "let conv1d(kernel: [#k]f32)(M: [#m]f32): []f32 =\n", " map (\\i -> reduce (+) 0f32 (map (*) kernel M[i:i+k]))\n", " (iota (m-k+1))\n", "\n", "entry f(x: f32): f32 = 6.28f32*x/360f32\n", " \n", "let main(): []f32 = conv1d [1.5f32, 0f32, 1f32] (map f32 (iota 100))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Use it\n", "\n", "* Entry points and `main` are available in the Notebook namespace" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.209333\n", "[ 2. 4.5 7. 9.5 12. 14.5 17. 19.5 22. 24.5\n", " 27. 29.5 32. 34.5 37. 39.5 42. 44.5 47. 49.5\n", " 52. 54.5 57. 59.5 62. 64.5 67. 69.5 72. 74.5\n", " 77. 79.5 82. 84.5 87. 89.5 92. 94.5 97. 99.5\n", " 102. 104.5 107. 109.5 112. 114.5 117. 119.5 122. 124.5\n", " 127. 129.5 132. 134.5 137. 139.5 142. 144.5 147. 149.5\n", " 152. 154.5 157. 159.5 162. 164.5 167. 169.5 172. 174.5\n", " 177. 179.5 182. 184.5 187. 189.5 192. 194.5 197. 199.5\n", " 202. 204.5 207. 209.5 212. 214.5 217. 219.5 222. 224.5\n", " 227. 229.5 232. 234.5 237. 239.5 242. 244.5]\n" ] } ], "source": [ "print(f(12))\n", "print(main())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Errors handling\n", "\n", "* Show errors from Futhark compiler" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[1mIn: main(): f32 =\u001b[0m\n", "Declaration of function main at tmpElpeLL.fut:2:7-2:7 declares return type f32, but body has type i32\n", "If you find this error message confusing, uninformative, or wrong, please open an issue at https://github.com/HIPERFIT/futhark/issues.\n" ] } ], "source": [ "%%futhark\n", "\n", "entry main(): f32 =\n", " 42" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Inspect internalization\n", "\n", "View how Futhark's compiler internalized a program using the `inspect` option. Defaults to cpu compilation pipeline, use the `gpu` option to view gpu-optimized output." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "entry [f32] f(f32 x_475) =\n", " let {f32 x_476} = fmul32(6.28f32, x_475)\n", " let {f32 res_477} = fdiv32(x_476, 360.0f32)\n", " in {res_477}\n", "\n", "entry [[?1]f32@2] main() =\n", " let {mem(12i64) mem_524} =\n", " alloc(12i64)\n", " -- arg_478 : [3i32]f32@mem_524->Direct(3i32)\n", " let {[3i32]f32 arg_478} = [1.5f32, 0.0f32, 1.0f32]\n", " let {mem(400i64) mem_527} =\n", " alloc(400i64)\n", " -- result_505 : [100i32]f32@mem_527->Direct(100i32)\n", " let {[100i32]f32 result_505} = scratch(f32, 100i32)\n", " -- arg_480 : [100i32]f32@mem_527->Direct(100i32)\n", " let {[100i32]f32 arg_480} =\n", " -- Consumes result_505\n", " -- map_outarr_506 : *[100i32]f32@mem_527->Direct(100i32)\n", " loop {*[100i32]f32 map_outarr_506} = {result_505}\n", " for i_504:i32 < 100i32 do {\n", " let {f32 res_482} = sitofp i32 i_504 to f32\n", " -- lw_dest_507 : [100i32]f32@mem_527->Direct(100i32)\n", " let {([100i32]f32 lw_dest_507 <- map_outarr_506)[i_504]} =\n", " -- Consumes map_outarr_506\n", " res_482\n", " in {lw_dest_507}\n", " }\n", " let {mem(392i64) mem_530} =\n", " alloc(392i64)\n", " -- result_515 : [98i32]f32@mem_530->Direct(98i32)\n", " let {[98i32]f32 result_515} = scratch(f32, 98i32)\n", " -- res_484 : [98i32]f32@mem_530->Direct(98i32)\n", " let {[98i32]f32 res_484} =\n", " -- Consumes result_515\n", " -- map_outarr_516 : *[98i32]f32@mem_530->Direct(98i32)\n", " loop {*[98i32]f32 map_outarr_516} = {result_515}\n", " for i_514:i32 < 98i32 do {\n", " let {f32 res_491} =\n", " loop {f32 acc_511} = {0.0f32}\n", " for i_510:i32 < 3i32 do {\n", " let {f32 binop_param_x_496} = arg_478[i_510]\n", " let {i32 j_p_i_t_s_521} = add32(i_514, i_510)\n", " let {f32 binop_param_y_497} = arg_480[j_p_i_t_s_521]\n", " let {f32 res_498} = fmul32(binop_param_x_496, binop_param_y_497)\n", " let {f32 res_499} = fadd32(acc_511, res_498)\n", " in {res_499}\n", " }\n", " -- lw_dest_517 : [98i32]f32@mem_530->Direct(98i32)\n", " let {([98i32]f32 lw_dest_517 <- map_outarr_516)[i_514]} =\n", " -- Consumes map_outarr_516\n", " res_491\n", " in {lw_dest_517}\n", " }\n", " in {res_484}\n" ] } ], "source": [ "%%futhark inspect\n", "\n", "let conv1d(kernel: [#k]f32)(M: [#m]f32): []f32 =\n", " map (\\i -> reduce (+) 0f32 (map (*) kernel M[i:i+k]))\n", " (iota (m-k+1))\n", "\n", "entry f(x: f32): f32 = 6.28f32*x/360f32\n", " \n", "let main(): []f32 = conv1d [1.5f32, 0f32, 1f32] (map f32 (iota 100))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" } }, "nbformat": 4, "nbformat_minor": 2 }