{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# GFloat Basics\n", "\n", "This notebook shows the use of `decode_float` to explore properties of some float formats.\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Install packages\n", "from pandas import DataFrame\n", "import numpy as np\n", "\n", "from gfloat import decode_float\n", "from gfloat.formats import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## List all the values in a format\n", "\n", "The first example shows how to list all values in a given format.\n", "We will choose the [OCP](https://www.opencompute.org/documents/ocp-8-bit-floating-point-specification-ofp8-revision-1-0-2023-12-01-pdf-1) E5M2 format.\n", "\n", "The object `format_info_ocp_e5m2` is from the `gfloat.formats` package, and describes the characteristics of that format:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "FormatInfo(name='ocp_e5m2', k=8, precision=3, emax=15, has_nz=True, has_infs=True, num_high_nans=3, has_subnormals=True, is_signed=True, is_twos_complement=False)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "format_info_ocp_e5m2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We shall use the format to decode all values from 0..255, and gather them in a pandas DataFrame.\n", "We see that `decode_float` returns a lot more than just the value - it also splits out the exponent, significand, and sign, and returns the `FloatClass`, which allows us to distinguish normal and subnormal numbers, as well as zero, infinity, and nan." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
fvalexpexpvalsignificandfsignificandsignbitfclass
code
00.000000e+000-1400.000FloatClass.ZERO
11.525879e-050-1410.250FloatClass.SUBNORMAL
23.051758e-050-1420.500FloatClass.SUBNORMAL
34.577637e-050-1430.750FloatClass.SUBNORMAL
46.103516e-051-1401.000FloatClass.NORMAL
........................
251-5.734400e+04301531.751FloatClass.NORMAL
252-inf311601.001FloatClass.INFINITE
253NaN311611.251FloatClass.NAN
254NaN311621.501FloatClass.NAN
255NaN311631.751FloatClass.NAN
\n", "

256 rows × 7 columns

\n", "
" ], "text/plain": [ " fval exp expval significand fsignificand signbit \\\n", "code \n", "0 0.000000e+00 0 -14 0 0.00 0 \n", "1 1.525879e-05 0 -14 1 0.25 0 \n", "2 3.051758e-05 0 -14 2 0.50 0 \n", "3 4.577637e-05 0 -14 3 0.75 0 \n", "4 6.103516e-05 1 -14 0 1.00 0 \n", "... ... ... ... ... ... ... \n", "251 -5.734400e+04 30 15 3 1.75 1 \n", "252 -inf 31 16 0 1.00 1 \n", "253 NaN 31 16 1 1.25 1 \n", "254 NaN 31 16 2 1.50 1 \n", "255 NaN 31 16 3 1.75 1 \n", "\n", " fclass \n", "code \n", "0 FloatClass.ZERO \n", "1 FloatClass.SUBNORMAL \n", "2 FloatClass.SUBNORMAL \n", "3 FloatClass.SUBNORMAL \n", "4 FloatClass.NORMAL \n", "... ... \n", "251 FloatClass.NORMAL \n", "252 FloatClass.INFINITE \n", "253 FloatClass.NAN \n", "254 FloatClass.NAN \n", "255 FloatClass.NAN \n", "\n", "[256 rows x 7 columns]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fmt = format_info_ocp_e5m2\n", "vals = [decode_float(fmt, i) for i in range(256)]\n", "DataFrame(vals).set_index(\"code\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot the values in some formats\n", "\n", "This is a plot of the positive values in each format, as a function of their integer \n", "codepoint. Subnormal values are indicated, illustrating the increased dynamic range \n", "they offer. (More on this below.)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/png": "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5LE2bdrg0qVLAGC8B/j/maYnMTERr732Gp566il06NABzzzzDF555RUsXLgQAO8NMqjJfRAYGFhlYHBZWRlycnJ4rzQRFQH84sWL2LFjh7EKDvD+qGsM4XVApVKhW7du2LVrl/ExvV6PXbt2IS4urh6vjGxNEARMnjwZW7ZswU8//YTIyEiT4926dYOTk5PJvXL27FlcunSJ90ojN3DgQJw6dQonT540/tW9e3eMHj3a+DXvjaard+/eVbYzPHfuHMLDwwEAkZGRCAwMNLk/8vPzcfjwYd4fjVxRURGUStM/vjk4OECv1wPgvUEGNbkP4uLikJubi+TkZONzfvrpJ+j1evTo0cPm10y2VRHA//rrL+zcuRM+Pj4mx3l/1LH6ngzXWG3atElwdnYW1q5dK/zxxx/CxIkTBS8vLyEjI6O+L41saNKkSYKnp6ewZ88e4dq1a8a/ioqKjM954YUXhLCwMOGnn34Sjh07JsTFxQlxcXH1eNVUXypPRxcE3htN2ZEjRwRHR0dhwYIFwl9//SVs2LBBUKvVwvr1643PeeuttwQvLy/h//7v/4TffvtN+Nvf/iZERkYKxcXF9XjlVNcSEhKE4OBg4dtvvxVSU1OFr776SvD19RVeffVV43N4bzQNt27dEk6cOCGcOHFCACAsXbpUOHHihHG6dU3ugwceeEDo0qWLcPjwYWHfvn1Cy5YthVGjRtXXRyIrkro/dDqdMHz4cCEkJEQ4efKkyZ9RtVqt8T14f9QdhvA6tHz5ciEsLExQqVRCbGyscOjQofq+JLIxAGb/+vTTT43PKS4uFl588UWhWbNmglqtFh555BHh2rVr9XfRVG/uDuG8N5q2b775Rmjfvr3g7OwstG7dWli1apXJcb1eL8ycOVMICAgQnJ2dhYEDBwpnz56tp6slW8nPzxdefvllISwsTHBxcRGioqKEN954w+QPzrw3mobdu3eb/TNGQkKCIAg1uw9u3LghjBo1SnB3dxc0Go0wbtw44datW/XwacjapO6P1NRU0T+j7t692/gevD/qjkIQBMF2dXciIiIiIiKipos94UREREREREQ2whBOREREREREZCMM4UREREREREQ2whBOREREREREZCMM4UREREREREQ2whBOREREREREZCMM4UREREREREQ2whBOREREREREZCMM4UREREREREQ2whBOREREREREZCMM4UREREREREQ28v/gp3aecU+HlAAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from matplotlib import pyplot as plt\n", "from gfloat import decode_ndarray\n", "\n", "plt.figure(figsize=(12, 4))\n", "code = np.arange(0, 256)\n", "for fi in (\n", " format_info_ocp_e4m3,\n", " format_info_ocp_e5m2,\n", " *(format_info_p3109(p) for p in (3, 4, 5)),\n", "):\n", " val = decode_ndarray(fi, code)\n", " valid = (val > 0) & np.isfinite(val)\n", " subnormal = val < fi.smallest_normal\n", " nsty = dict(marker=\"o\", markersize=3.5, linestyle=\"None\")\n", " (p,) = plt.plot(\n", " code[valid & ~subnormal], val[valid & ~subnormal], label=fi.name, **nsty\n", " )\n", " snsty = dict(marker=\"o\", markersize=3.5, linestyle=\"None\", markerfacecolor=\"none\")\n", " (hsub,) = plt.plot(\n", " code[valid & subnormal],\n", " val[valid & subnormal],\n", " label=None,\n", " color=p.get_color(),\n", " **snsty,\n", " )\n", "\n", "plt.plot(np.nan, np.nan, label=\"Subnormal values\", color=\"k\", **snsty)\n", "plt.yscale(\"log\")\n", "plt.legend()\n", "None # suppress output" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Additional format info: special values, min, max, dynamic range\n", "\n", "In addition, `FormatInfo` can tell us about other characteristics of each format.\n", "To reproduce some of the OCP spec's tables 1 and 2:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Format ocp_e4m3 ocp_e5m2 p3109_p3\n", "Max exponent (emax) 8 15 15\n", "Exponent bias 7 15 16\n", "Infinities 0 2 2\n", "Number of NaNs 2 6 1\n", "Number of zeros 2 2 1\n", "Max normal number 448.0 57344.0 49152.0\n", "Min normal number 0.015625 6.103515625e-05 3.0517578125e-05\n", "Min subnormal number 0.001953125 1.52587890625e-05 7.62939453125e-06\n", "Dynamic range (binades) 18 32 33\n" ] } ], "source": [ "def compute_dynamic_range(fi):\n", " return np.log2(fi.max / fi.smallest)\n", "\n", "\n", "for prop, probe in (\n", " (\"Format \", lambda fi: fi.name.replace(\"format_info_\", \"\")),\n", " (\"Max exponent (emax) \", lambda fi: fi.emax),\n", " (\"Exponent bias \", lambda fi: fi.expBias),\n", " (\"Infinities \", lambda fi: 2 * int(fi.has_infs)),\n", " (\"Number of NaNs \", lambda fi: fi.num_nans),\n", " (\"Number of zeros \", lambda fi: int(fi.has_zero) + int(fi.has_nz)),\n", " (\"Max normal number \", lambda fi: fi.max),\n", " (\"Min normal number \", lambda fi: fi.smallest_normal),\n", " (\"Min subnormal number \", lambda fi: fi.smallest_subnormal),\n", " (\"Dynamic range (binades)\", lambda x: round(compute_dynamic_range(x))),\n", "):\n", " print(\n", " f\"{prop} {probe(format_info_ocp_e4m3):<20} {probe(format_info_ocp_e5m2):<20} {probe(format_info_p3109(3))}\"\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## How do subnormals affect dynamic range?\n", "\n", "Most, if not all, low-precision formats include subnormal numbers, as they increase the number of values near zero, and increase dynamic range.\n", "A natural question is \"by how much?\". To answer this, we can create a mythical new format, a copy of `e4m3`, but with `has_subnormals` set to true." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "import copy\n", "\n", "e4m3_no_subnormals = copy.copy(format_info_ocp_e4m3)\n", "e4m3_no_subnormals.has_subnormals = False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And now compute the dynamic range with and without:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dynamic range with subnormals = 17.807354922057606\n", "Dynamic range without subnormals = 15.637429920615292\n", "Ratio = 4.5\n" ] } ], "source": [ "dr_with = compute_dynamic_range(format_info_ocp_e4m3)\n", "dr_without = compute_dynamic_range(e4m3_no_subnormals)\n", "\n", "print(f\"Dynamic range with subnormals = {dr_with}\")\n", "print(f\"Dynamic range without subnormals = {dr_without}\")\n", "print(f\"Ratio = {2**(dr_with - dr_without):.1f}\")" ] } ], "metadata": { "kernelspec": { "display_name": "ml_dtypes", "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.10.0" } }, "nbformat": 4, "nbformat_minor": 2 }