-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'gt4py-workshop' of https://github.com/GridTools/gt4py i…
…nto gt4py-workshop
- Loading branch information
Showing
5 changed files
with
966 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,289 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"id": "4598486a", | ||
"metadata": {}, | ||
"source": [ | ||
"<img src=\"logos/cscs_logo.jpeg\" alt=\"cscs\" style=\"width:270px;\"/> <img src=\"logos/c2sm_logo.gif\" alt=\"c2sm\" style=\"width:220px;\"/>\n", | ||
"<img src=\"logos/exclaim_logo.png\" alt=\"exclaim\" style=\"width:270px;\"/> <img src=\"logos/mch_logo.svg\" alt=\"mch\" style=\"width:270px;\"/>" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "c5abdaa5", | ||
"metadata": {}, | ||
"source": [ | ||
"# GT4Py workshop" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "64c0b236", | ||
"metadata": {}, | ||
"source": [ | ||
"## GT4Py: GridTools for Python\n", | ||
"\n", | ||
"GT4Py is a Python library for generating high performance implementations of stencil kernels from a high-level definition using regular Python functions.\n", | ||
"\n", | ||
"GT4Py is part of the GridTools framework: a set of libraries and utilities to develop performance portable applications in the area of weather and climate modeling.\n", | ||
"\n", | ||
"**NOTE:** The `gt4py.next` subpackage contains a new and currently experimental version of GT4Py.\n", | ||
"\n", | ||
"## Description\n", | ||
"\n", | ||
"GT4Py is a Python library for expressing computational motifs as found in weather and climate applications. \n", | ||
"\n", | ||
"These computations are expressed in a domain specific language (DSL) which is translated to high-performance implementations for CPUs and GPUs.\n", | ||
"\n", | ||
"In addition, GT4Py provides functions to allocate arrays with memory layout suited for a particular backend.\n", | ||
"\n", | ||
"The following backends are supported:\n", | ||
"- `None` aka _embedded_: runs the DSL code directly via the Python interpreter (experimental)\n", | ||
"- `gtfn_cpu` and `gtfn_gpu`: transpiles the DSL to C++ code using the GridTools library\n", | ||
"- `dace`: uses the DaCe library to generate optimized code (experimental)\n", | ||
"\n", | ||
"In this workshop we will mainly use the _embedded_ backend.\n", | ||
"\n", | ||
"## Current efforts\n", | ||
"\n", | ||
"GT4Py is being used to port the ICON model from FORTRAN. Currently the **dycore**, **diffusion**, and **microphysics** are complete. \n", | ||
"\n", | ||
"The ultimate goal is to have a more flexible and modularized model that can be run on CSCS Alps infrastructure as well as other hardware.\n", | ||
"\n", | ||
"Other models ported using GT4Py are ECMWF's FVM, in global (with `gt4py.next` and local area configuration (with `gt4py.cartesian`) and GFDL's FV3 (with `gt4py.cartesian`; original port by AI2)." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "d84571cc", | ||
"metadata": {}, | ||
"source": [ | ||
"## Installation and setup\n", | ||
"\n", | ||
"Get an account from https://docs.google.com/document/d/1SuMr2sEdsGHGcnSFczNLGdTVYvNuuXBpCqB-3zL1E9c/edit?usp=sharing and mark with your name.\n", | ||
"\n", | ||
"After cloning the repository to $SCRATCH and setting a symlink to your home-directory\n", | ||
"\n", | ||
"```\n", | ||
"cd $SCRATCH\n", | ||
"git clone --branch gt4py-workshop https://github.com/GridTools/gt4py.git\n", | ||
"cd $HOME\n", | ||
"ln -s $SCRATCH/gt4py\n", | ||
"```\n", | ||
"\n", | ||
"you can install the library with pip.\n", | ||
"\n", | ||
"Make sure that GT4Py is in the expected location, remove `#` and run the cell)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "d55089eb", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#! pip install $HOME/gt4py" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "e25b300a", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import warnings\n", | ||
"warnings.filterwarnings('ignore')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "4ac0ca57", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import numpy as np\n", | ||
"import gt4py.next as gtx\n", | ||
"from gt4py.next import float64, neighbor_sum, where" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "219a8afd", | ||
"metadata": {}, | ||
"source": [ | ||
"## Key concepts and application structure\n", | ||
"\n", | ||
"- [Fields](#Fields),\n", | ||
"- [Field operators](#Field-operators), and\n", | ||
"- [Programs](#Programs)." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "332533a3", | ||
"metadata": {}, | ||
"source": [ | ||
"### Fields\n", | ||
"Fields are **multi-dimensional array** defined over a set of dimensions and a dtype: `gtx.Field[[dimensions], dtype]`.\n", | ||
"\n", | ||
"| <div><img src=\"../images/field.png\" width=\"66%\"/></div> |\n", | ||
"| :-----------------------------------------: |\n", | ||
"| <div><img src=\"../images/field-code.png\" width=\"50%\"/></div> |" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "437cad42", | ||
"metadata": {}, | ||
"source": [ | ||
"Fields can be constructed with the following functions, inspired by numpy:\n", | ||
"\n", | ||
"- `zeros`\n", | ||
"- `full` to fill with a given value\n", | ||
"- `as_field` to convert from numpy or cupy arrays\n", | ||
"\n", | ||
"The first argument is the domain of the field, which can be constructed from a mapping from `Dimension` to range.\n", | ||
"\n", | ||
"Optional we can pass\n", | ||
"- `dtype` the description of type of the field\n", | ||
"- `allocator` which describes how and where (e.g. GPU) the buffer is allocated.\n", | ||
"\n", | ||
"Note: `as_field` can also take a sequence of Dimensions and infer the shape" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "f4be5a76", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"Cell = gtx.Dimension(\"Cell\")\n", | ||
"K = gtx.Dimension(\"K\", kind=gtx.DimensionKind.VERTICAL)\n", | ||
"\n", | ||
"domain = gtx.domain({Cell: 5, K: 6})\n", | ||
"\n", | ||
"a = gtx.zeros(domain, dtype=float64)\n", | ||
"b = gtx.full(domain, fill_value=3.0, dtype=float64)\n", | ||
"c = gtx.as_field([Cell, K], np.fromfunction(lambda c, k: c*10+k, shape=domain.shape))\n", | ||
"\n", | ||
"print(\"a definition: \\n {}\".format(a))\n", | ||
"print(\"a array: \\n {}\".format(a.asnumpy()))\n", | ||
"print(\"b array: \\n {}\".format(b.asnumpy()))\n", | ||
"print(\"c array: \\n {}\".format(c.asnumpy()))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "f7875b85", | ||
"metadata": {}, | ||
"source": [ | ||
"### Field operators\n", | ||
"\n", | ||
"Field operators perform operations on a set of fields, i.e. elementwise addition or reduction along a dimension. \n", | ||
"\n", | ||
"They are written as Python functions by using the `@field_operator` decorator." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "7092af27", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"@gtx.field_operator\n", | ||
"def add(a: gtx.Field[[Cell, K], float64],\n", | ||
" b: gtx.Field[[Cell, K], float64]) -> gtx.Field[[Cell, K], float64]:\n", | ||
" return a + b" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "ba88d740", | ||
"metadata": {}, | ||
"source": [ | ||
"Direct calls to field operators require two additional arguments: \n", | ||
"- `out`: a field to write the return value to\n", | ||
"- `offset_provider`: empty dict for now, explanation will follow" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "e93f8d29", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"result = gtx.zeros(domain)\n", | ||
"add(a, b, out=result, offset_provider={})\n", | ||
"\n", | ||
"print(\"result array \\n {}\".format(result.asnumpy()))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "b482c77c", | ||
"metadata": {}, | ||
"source": [ | ||
"### Programs" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "2b5dbfe8", | ||
"metadata": {}, | ||
"source": [ | ||
"Programs are used to call field operators to mutate the latter's output arguments.\n", | ||
"\n", | ||
"They are written as Python functions by using the `@program` decorator. \n", | ||
"\n", | ||
"This example below calls the `add` field operator twice:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "7ff60fda", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"@gtx.program\n", | ||
"def run_add(a : gtx.Field[[Cell, K], float64],\n", | ||
" b : gtx.Field[[Cell, K], float64],\n", | ||
" result : gtx.Field[[Cell, K], float64]):\n", | ||
" add(a, b, out=result)\n", | ||
" add(b, result, out=result)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "08713dc1", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"result = gtx.zeros(domain, dtype=float64)\n", | ||
"run_add(a, b, result, offset_provider={})\n", | ||
"\n", | ||
"print(\"result array: \\n {}\".format(result.asnumpy()))" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"jupytext": { | ||
"formats": "ipynb,md:myst" | ||
}, | ||
"kernelspec": { | ||
"display_name": "Python 3 (ipykernel)", | ||
"language": "python", | ||
"name": "python3" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
Oops, something went wrong.