diff --git a/README.md b/README.md index 193fd94..7caa10a 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ This repository contains a variety of Determined examples that are not actively | [LLM Finetuning 2](blog/llm-finetuning-2) | Finetuning Mistral-7B on Text-to-SQL using LoRA and DeepSpeed. | | [LLM Finetuning 3](blog/llm-finetuning-3) | Finetuning Gemma-2B using DPO. | | [Python SDK demo](blog/python_sdk_demo) | Example usage of the Determined Python SDK to run and administer experiments. | +| [Tensor Parallelism](blog/tp) | Profiling tensor parallelism in PyTorch. | ## Computer Vision diff --git a/blog/act-mem-2/README.md b/blog/act-mem-2/README.md index 07f1547..9531f4c 100644 --- a/blog/act-mem-2/README.md +++ b/blog/act-mem-2/README.md @@ -9,3 +9,8 @@ memory. - `attn_script.py` shows the cost of activation memory in the attention layer. - Tests of the code are in `test.py`. - See `requirements.txt` for versions the code was built against. + + +## Contributors + +- [Garrett Goon](https://github.com/garrett361) \ No newline at end of file diff --git a/blog/tp/README.md b/blog/tp/README.md new file mode 100644 index 0000000..79ea909 --- /dev/null +++ b/blog/tp/README.md @@ -0,0 +1,13 @@ +# Tensor Parallelism + +Code accompanying the deep-dive [blog post on Tensor Parallelism](https://determined.ai/blog/tp). + +- The MLP and TP MLP layers are in `layer.py` +- Matmul profiling code in `matmul_profiling.py` +- MLP TP profiling code in `tp_profiling.py` +- Tests of the rearranging tensor sums are in `test_dot_product_{local,distributed}.py` + + +## Contributors + +- [Garrett Goon](https://github.com/garrett361) \ No newline at end of file diff --git a/blog/tp/layers.py b/blog/tp/layers.py new file mode 100644 index 0000000..f559742 --- /dev/null +++ b/blog/tp/layers.py @@ -0,0 +1,138 @@ +from typing import Any, Optional, Union + +import torch +import torch.distributed as dist +import torch.nn as nn + + +class MLP(nn.Module): + """ + Basic MLP (multi-layer perceptron) layer. Dropout is neglected. + """ + + def __init__( + self, + d_model: int, + device: Optional[Union[str, torch.device]] = None, + dtype: Optional[torch.dtype] = None, + ) -> None: + super().__init__() + + self.lin_0 = nn.Linear(d_model, 4 * d_model, device=device, dtype=dtype) + self.act_fn = nn.GELU() + self.lin_1 = nn.Linear(4 * d_model, d_model, device=device, dtype=dtype) + + def forward(self, inputs: torch.Tensor) -> torch.Tensor: + x = self.lin_0(inputs) + x = self.act_fn(x) + x = self.lin_1(x) + return x + + +class AllReduceFwdIdentityBwd(torch.autograd.Function): + @staticmethod + def forward( + ctx: Any, inputs: torch.Tensor, group: Optional[dist.ProcessGroup] = None + ) -> torch.Tensor: + inputs = inputs.clone() + dist.all_reduce(inputs, group=group) + return inputs + + @staticmethod + def backward(ctx: Any, grad_outputs: torch.Tensor) -> tuple[torch.Tensor, None]: + return grad_outputs, None + + +class IdentityFwdAllReduceBwd(torch.autograd.Function): + @staticmethod + def forward( + ctx: Any, inputs: torch.Tensor, group: Optional[dist.ProcessGroup] = None + ) -> torch.Tensor: + ctx.group = group + return inputs + + @staticmethod + def backward(ctx: Any, grad_outputs: torch.Tensor) -> tuple[torch.Tensor, None]: + grad_outputs = grad_outputs.clone() + dist.all_reduce(grad_outputs, group=ctx.group) + return grad_outputs, None + + +class LinearShardedOutputs(nn.Linear): + def __init__( + self, + in_features: int, + out_features: int, + group: dist.ProcessGroup, + device: Optional[Union[str, torch.device]] = None, + dtype: Optional[torch.dtype] = None, + ) -> None: + sharded_out_features, remainder = divmod(out_features, group.size()) + assert not remainder, "out_features must be divisible by the ProcessGroup size" + super().__init__( + in_features=in_features, + out_features=sharded_out_features, + device=device, + dtype=dtype, + ) + + self.group = group + + def forward(self, inputs: torch.Tensor) -> torch.Tensor: + # Wrap the unsharded inputs for backwards-pass correctness. + x = IdentityFwdAllReduceBwd.apply(inputs, self.group) + x = super().forward(x) + return x + + +class LinearShardedInputs(nn.Linear): + def __init__( + self, + in_features: int, + out_features: int, + group: dist.ProcessGroup, + device: Optional[Union[str, torch.device]] = None, + dtype: Optional[torch.dtype] = None, + ) -> None: + sharded_in_features, remainder = divmod(in_features, group.size()) + assert not remainder, "in_features must be divisible by the ProcessGroup size" + super().__init__( + in_features=sharded_in_features, + out_features=out_features, + device=device, + dtype=dtype, + ) + self.group = group + + def forward(self, inputs: torch.Tensor) -> torch.Tensor: + x = inputs @ self.weight.T + # Wrap the mat-mul in an all-reduce forwards-pass correctness. + x = AllReduceFwdIdentityBwd.apply(x, self.group) + # Crucial: add the bias _after_ the all-reduce. + x = x + self.bias + return x + + +class MLPTP(MLP): + """ + Basic Tensor Parallel MLP (multi-layer perceptron) layer. Dropout is neglected. + """ + + def __init__( + self, + d_model: int, + group: Optional[dist.ProcessGroup] = None, + device: Optional[Union[str, torch.device]] = None, + dtype: Optional[torch.dtype] = None, + ) -> None: + nn.Module.__init__(self) + # Fallback to the WORLD process group, if None provided + group = group or dist.group.WORLD + + self.lin_0 = LinearShardedOutputs( + d_model, 4 * d_model, group=group, device=device, dtype=dtype + ) + self.act_fn = nn.GELU() + self.lin_1 = LinearShardedInputs( + 4 * d_model, d_model, group=group, device=device, dtype=dtype + ) diff --git a/blog/tp/matmul.png b/blog/tp/matmul.png new file mode 100644 index 0000000..f23da74 Binary files /dev/null and b/blog/tp/matmul.png differ diff --git a/blog/tp/matmul_profiling.py b/blog/tp/matmul_profiling.py new file mode 100644 index 0000000..91ac4e6 --- /dev/null +++ b/blog/tp/matmul_profiling.py @@ -0,0 +1,91 @@ +import gc +import logging + +import determined as det +import torch + +import utils + +""" +Script for profiling square matmuls on a single GPU. +""" + + +def profile_and_report( + core_context: det.core.Context, + d_model: int, + num_repeats: int, + num_warmups: int, + dtype: torch.dtype = torch.bfloat16, +) -> None: + A = torch.randn(d_model, d_model, device="cuda", dtype=dtype) + B = torch.randn(d_model, d_model, device="cuda", dtype=dtype) + + # Use CUDA events for accurate timing. + timer = utils.CUDAEventTimer() + torch.cuda.synchronize() + + # Warmups + for _ in range(num_warmups): + A @ B + + # Timed region. + for _ in range(num_repeats): + with timer: + A @ B + + # Mean and std TFLOP computations + flops = 2 * d_model**3 + time_s_t = torch.tensor(timer.time_s_list) + tflop_s_gpu_t = flops / time_s_t / 1e12 + metrics = { + "d_model": d_model, + "time_s": timer.time_s_mean, + "time_s_std": timer.time_s_std, + "tflop_s_gpu": tflop_s_gpu_t.mean().item(), + "tflop_s_gpu_std": tflop_s_gpu_t.std().item(), + } + + # Use d_model as the x-axis for plotting purposes. + core_context.train.report_metrics(group="matmul", steps_completed=d_model, metrics=metrics) + + # Memory management + del A + del B + gc.collect() + torch.cuda.empty_cache() + + +def main( + core_context: det.core.Context, + d_model_min: int, + d_model_max: int, + d_model_step: int, + num_repeats: int, + num_warmups: int, +) -> None: + for d_model in range(d_model_min, d_model_max + 1, d_model_step): + profile_and_report( + core_context=core_context, + d_model=d_model, + num_repeats=num_repeats, + num_warmups=num_warmups, + ) + + +if __name__ == "__main__": + info = det.get_cluster_info() + assert info, "This script must run on a determined cluster." + hparams = info.trial.hparams + + with det.core.init() as core_context: + logging.basicConfig(level=logging.INFO, format=det.LOG_FORMAT) + + main( + core_context=core_context, + d_model_min=hparams["d_model_min"], + d_model_max=hparams["d_model_max"], + d_model_step=hparams["d_model_step"], + num_repeats=hparams["num_repeats"], + num_warmups=hparams["num_warmups"], + ) diff --git a/blog/tp/matmul_profiling.yaml b/blog/tp/matmul_profiling.yaml new file mode 100644 index 0000000..97674dd --- /dev/null +++ b/blog/tp/matmul_profiling.yaml @@ -0,0 +1,20 @@ +name: Matmul Profiling +# Adjust the workspace and project names, as appropriate. +workspace: TP Blog Post +project: Matmul Profiling +resources: + slots_per_trial: 1 +searcher: + name: single + metric: not_used + max_length: 1 +hyperparameters: + d_model_min: 256 + d_model_max: 16384 + d_model_step: 256 + num_warmups: 5 + num_repeats: 100 +entrypoint: >- + python3 -m determined.launch.torch_distributed + python3 matmul_profiling.py +max_restarts: 0 diff --git a/blog/tp/mlp_tp.png b/blog/tp/mlp_tp.png new file mode 100644 index 0000000..1aff737 Binary files /dev/null and b/blog/tp/mlp_tp.png differ diff --git a/blog/tp/plots.ipynb b/blog/tp/plots.ipynb new file mode 100644 index 0000000..a0663e6 --- /dev/null +++ b/blog/tp/plots.ipynb @@ -0,0 +1,470 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6cf61f44-e76f-435a-a4c4-7882c1546d52", + "metadata": {}, + "source": [ + "# Plots" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1b461d37-b6de-42b7-9b03-063f3c46ef93", + "metadata": {}, + "outputs": [], + "source": [ + "import determined as det\n", + "from collections import defaultdict\n", + "from determined.experimental import client\n", + "import pandas as pd\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "\n", + "sns.set_theme(style=\"darkgrid\")\n", + "sns.set(rc={\"figure.figsize\": (7.5, 7.5)})\n" + ] + }, + { + "cell_type": "markdown", + "id": "b1be1013-61b9-4290-95e7-891e9cbe0eb5", + "metadata": {}, + "source": [ + "Get all projects in the workspace" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "27c9f4dc-f0b8-45c9-ba3e-5c1ff398b8d3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MLP TP Profiling\n", + "Matmul Profiling\n", + "obsolete\n" + ] + } + ], + "source": [ + "workspace = client.get_workspace(\"TP Blog Post\")\n", + "projects_dict = {p.name: p for p in workspace.list_projects()}\n", + "for p in projects_dict:\n", + " print(p)" + ] + }, + { + "cell_type": "markdown", + "id": "5703a1f3-24b5-4d7c-acdd-3c14bf88f4af", + "metadata": {}, + "source": [ + "## Matmul Plots" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d94ce58b-497c-46de-ac9d-57c8a2c053e1", + "metadata": {}, + "outputs": [], + "source": [ + "matmul_trial = projects_dict[\"Matmul Profiling\"].list_experiments()[0].list_trials()[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "996c7686-7c1d-4de2-8a8a-f46453272b41", + "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", + "
d_modelTFLOP/sec/GPUTFLOP/sec/GPU_std
02561.0436840.065087
15128.5082061.398408
276829.9998401.571498
3102449.3716813.053242
41280111.7303544.155525
............
5915360267.5995182.319973
6015616268.2694402.898224
6115872267.0128784.683553
6216128267.3208314.209327
6316384268.2875373.332946
\n", + "

64 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " d_model TFLOP/sec/GPU TFLOP/sec/GPU_std\n", + "0 256 1.043684 0.065087\n", + "1 512 8.508206 1.398408\n", + "2 768 29.999840 1.571498\n", + "3 1024 49.371681 3.053242\n", + "4 1280 111.730354 4.155525\n", + ".. ... ... ...\n", + "59 15360 267.599518 2.319973\n", + "60 15616 268.269440 2.898224\n", + "61 15872 267.012878 4.683553\n", + "62 16128 267.320831 4.209327\n", + "63 16384 268.287537 3.332946\n", + "\n", + "[64 rows x 3 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "matmul_results_dict = defaultdict(list)\n", + "for m in matmul_trial.iter_metrics(\"matmul\"):\n", + " matmul_results_dict[\"d_model\"].append(m.metrics[\"d_model\"])\n", + " matmul_results_dict[\"TFLOP/sec/GPU\"].append(m.metrics[\"tflop_s_gpu\"])\n", + " matmul_results_dict[\"TFLOP/sec/GPU_std\"].append(m.metrics[\"tflop_s_gpu_std\"])\n", + "matmul_results_df = pd.DataFrame.from_dict(matmul_results_dict)\n", + "matmul_results_df" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "d47fdb30-a4be-493e-8a02-7e190c75c82c", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAApQAAALQCAYAAAAuBuBGAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABsNUlEQVR4nO3deXhTZd7G8TttulKKBQoogiJKkaVQoAgii1UBB3FeQEUFFFcUkBkBRQVXRhEBZQQRHUAExAVZ1HEQAVeQrVjBESiCiGtpWUvpmuS8fzCJxC5Je9Imab+f6/KSnufkyXN+SU/vPGeJxTAMQwAAAEAFhfh7AAAAAAhuBEoAAACYQqAEAACAKQRKAAAAmEKgBAAAgCkESgAAAJhCoAQAAIApBEoAAACYQqAEAACAKVZ/DwBA2davX6933nlHO3fu1MmTJ3XWWWepbdu2uu6663TFFVf4e3hV7qGHHtLKlSslSc8995z++te/lrruPffco08//VSSlJ6eXqHns9vtevPNNzVw4EBFR0dXqA+zhg0bpq1bt2rbtm2KjY0tcZ2UlBT9+uuvXvU3evRo3XfffZo1a5Zmz57tcf1Vq1bp4osv1ooVK/Twww+7Hu+t48ePa9GiRfr000/1008/yeFw6Nxzz1W3bt00ZMgQNWnSpNhjznydzxQWFqbatWurVatWuuWWW9SzZ88Sn/O2225T7dq19eKLL3o9TgAVR6AEAtjkyZO1ZMkSNW7cWFdccYXi4uJ06NAhff755/rkk090ww03aPLkyf4ept+sXbu21ECZk5OjjRs3mn6OcePGafXq1br22mtN91WZbrnlFp08edL1c3Z2thYtWqTGjRtrwIABbut27tzZ7ecrrrhCF198cal9169fv8Lj2rRpk/72t7/pxIkTat26tQYOHKjQ0FClp6dr4cKFWrJkiR577DHdcMMNJT5+wIABaty4setnm82m33//XR999JE2bNigf/zjH7r++uvdHpOXl6fU1FQ9+uijFR43gPIhUAIBasuWLVqyZIn69Omj559/XlbrH7+uJ0+e1C233KJ33nlHPXv21JVXXunHkfpHfHy8NmzYoLy8PEVFRRVr//TTT1VYWKjo6Gjl5uZW+HmOHDliZphVZvjw4W4///LLL65A6Wk28corr9TAgQN9PqbvvvtOd999tyIiIvTSSy8Ve5/u3r1bI0eO1KOPPiqLxVIsGEqnA+Ull1xSbPngwYM1ZMgQPfvss7rmmmvc3gNbt25VYWGhunXr5vNtAlAyzqEEAtRnn30mSRoyZIhbmJSk2rVra9y4cZJOz9LVRFdccYXy8vK0YcOGEtvXrFmj5s2bq2nTplU8Mjg98sgjKiws1MyZM0v80HPxxRdr4cKFCg8P17PPPqusrCyv++7YsaOSkpKUk5Oj7du3u7Vt2LBBzZo1c5vZBFC5CJRAgCoqKpIk7d27t8T2Tp06aebMmcVmpgoKCvTCCy8oJSVFiYmJuv7667V161Y99NBDSkhIcK23YsUKJSQkaOHChcX6HjZsmBISEpSdne02ntdff1033HCDOnbsqDZt2ujyyy/XY489pqNHj7rW++WXX5SQkKB//vOf+sc//qH27dvrkksu0erVqyVJhmHozTff1IABA5SYmKjk5GTdc8892rVrV7nqc+WVVyokJEQff/xxsbbc3Fx9+eWX6tOnT4mP9XZbEhIStHXrVklScnKyhg0bJkmaNWuWEhIS9OOPP+q5557TZZddpnbt2unGG2/Ut99+K4fDoX/9619KSUlR+/btdd1112nLli1uY0hJSVGnTp2KjW3Lli1KSEjQ008/Xa56BJotW7Zoz5496tSpky677LJS1zvvvPM0ePBg5eTk6IMPPijXczRs2FDS6XM0z7Rhwwa35zx8+LAeeeQRXXXVVWrbtq0uu+wyPfDAAzp48GCxPg8ePKjx48fr0ksvVZs2bXT11VfrlVdecf0+numXX37RxIkT1aNHD7Vr1079+vXTggULSlwXqO4IlECAch6umzp1qiZPnqy0tDTZ7XZXe2RkpK6++mq3c9/sdrtuv/12zZ07V3FxcRoyZIgiIyN1xx13aPfu3abGM27cOD3zzDOyWq264YYbNHjwYIWHh+vtt9/WXXfdVWz9d955R6tXr9ZNN92k9u3bq3379pKkCRMm6IknnlBRUZFuvPFG9e3bV6mpqbrxxhu1adMmr8dTv359dezYUZ999lmxP+CfffaZ8vPz1bdvX1PbMnr0aNcs11133VXsXMS///3vWr16tfr166eePXsqLS1Nd955pyZOnKgFCxaoR48euvrqq7V7927dc889OnTokNfbF+y++uorSVKPHj08rnvVVVdJktatW1eu5/jpp58k/REsJem3337TDz/84AqUBQUFuuuuu/Tee++pdevWGj58uDp27KgPP/xQN954o1sY/e677zRo0CB99NFH6tKli4YPH646dero+eef17333uv2+7d3714NGjRIy5cvV6tWrXTzzTcrMjJSU6dO1aRJk8q1HUB1wDmUQIC6/PLLddNNN+nNN9/UkiVLtGTJEsXExKhjx4669NJL1bdvXzVq1MjtMcuWLVNqaqoGDBigZ555RiEhpz8zPv3001q0aFGFx/LNN99ozZo16t+/v6ZPn+5abrPZNGDAAP33v//VgQMH1KxZM1fbkSNHtGrVKrVs2dK1bPXq1Xrvvfd0zTXXaOrUqa5D+Xfffbeuu+46TZgwQevWrVN4eLhX4+rdu7e2bdumLVu2uM1IrVmzRs2aNXObka3Ittx3333aunWrfv31V919993FrrDOzs7We++951o+btw4/fvf/9bHH3+s//znP66g07hxY82aNUvr16/XzTff7NW2VaV169aVeoX4rbfeWuqV5WU5cOCAJLm9J0rTvHlzSdLPP//sdf/r1q3Td999pwYNGqhdu3au5Rs2bFBYWJjrwqOvvvpKu3bt0qhRozRmzBjXevPnz9dzzz2nDz/8UEOGDJFhGHrooYdUWFiot956S23atHGtO2XKFC1cuFBvvfWWhgwZIkl68skndeLECb344ovq3bu3pNOz73feeadWrVqlW265Ra1bt/Z6e4BgR6AEAtgTTzyhXr16acmSJdq8ebNycnL0+eef6/PPP9e0adN0++236/7773cFxw8//FAWi0Xjxo1zLZNOB52VK1e6XQVcHo0aNdKzzz5b7BCt1WpVx44dtXfvXh05csQtPJx33nluYVKS3n33XUnSxIkT3c4LbdKkiW688UbNnTtXX331lXr16uXVuHr37q1nnnlGH3/8sStQ5ufn64svvtCtt97qs20pzcCBA93CVocOHfTvf/9b/fr1c5s1S0xMlCSvb+tT1davX6/169eX2DZgwIAKBcqcnBxJUkxMjMd169SpI0k6duxYsbaVK1e6TjuQpMLCQqWnp2vDhg2yWq164okn3D6AbNiwQR07dnTd4snhcEg6fduogoICRURESJJuvvlm/eUvf3F9KNuxY4f27t2rIUOGuIVJSfrb3/6mN954QytWrNCQIUOUkZGh1NRUdevWzRUmJclisWjs2LFq37691x+KgOqCQAkEuF69eqlXr146deqUUlNTtWnTJn3yySc6ePCgXn31VTkcDj3wwAOSTh+GO/vssxUfH+/WR2RkpNq1a1fqBSyeNGrUSAMGDJDNZtN3332nAwcO6KefftLu3btdhzadf7idzj333GL9fPfdd4qIiNAbb7xRrM05o7V7926vA2WjRo2UmJioTz75RE888YRCQkL0xRdfKDc3t9TD3RXZltL8+YIf55XGf952Z4gpLCz0qt+qNmXKFJ9f5e0Mofn5+R7XzcvLkyTVrVu3WNuf70UZHh6u+vXrq2/fvho+fLgrrEunT/nYtGmT22kLl156qZo0aaJ169bp0ksv1aWXXqoePXqoV69eOvvss13rfffdd5JOH0afNWtWsXHUqlVL6enpMgzDdU9T52kcZ2rdujUzk6iRCJRAkKhVq5Z69uypnj17asKECXr33Xf16KOPasmSJRo9erSioqKUk5NT6j0DzzrrLFPP/9Zbb+mll15SZmampNOBoV27dmrevLl27NghwzDc1neGqDOdPHlSNputzJtpnzhxolzj6t27t6ZNm6a0tDR17NhRa9as0fnnn19sdtTMtpSmtBudMzv1R9j+8ccfPa67b98+SdI555xTrG3RokUl3jaoJDt27FB2dra6d+/uWhYVFaV33nlHL7/8slavXq2PP/5YH3/8sUJCQnTVVVfpqaee0llnneW6AO3LL7/Ul19+WepznDp1yvUe9Wb2FagpuCgHCEA5OTnq3bu3RowYUWK785593bp1U35+vjIyMiSdDkal3Xrlz4cTLRaLJJUYnpwzRk6rV6/W448/rri4OL300kv67LPPtG3bNs2bN6/MG2L/WXR0tM4++2ylp6eX+t9DDz3kdX+SXFdyr127VoWFhfr0009LnZ305bb4Qkkzod7M6AUD522CvLnQ5pNPPnF7TEVt2LBB9evXL/Zhom7dupo4caK+/PJLvffeexo/fryaN2+uNWvW6IknnpD0x4eDp59+usz3Z0xMjGvdU6dOFRuDw+GoNq8hUB4ESiAAxcTE6OTJk/rqq690+PDhMtcNCQlxHeJu06aNTpw4oR9++MFtncLCwmK3HwoLC5OkYjf9Ngyj2MUR//73vyVJM2bM0JVXXul2qND5XN7M6iUkJCgjI6PE0PvZZ5/phRde0J49ezz2c6YmTZro4osv1rp167Rx40adOnWqzEDpq20xKywsTAUFBcWey3nlcrBLTExUu3bttH379jJD5S+//KI333xT0dHR6t+/v6nn3LBhgy699FLXhyVJ2rZtm/7xj3/op59+ksViUcuWLXXXXXdp2bJlio6OVmpqqiS5LuD673//W6zfoqIiPfvss1q8eLHbujt37iy2blpamtq3b6+XX37Z1LYAwYZACQSoIUOGqLCwUGPGjHEdmj3T+vXr9dVXX+mqq65yHXpzfn3d1KlT3c7XmzdvXrEQd8EFF0g6fYjvzNuhLF26tNh9/ZyHr/8cbletWuW6YMJms3ncpgEDBsgwDE2ePNltfJmZmXr88cf16quvqlatWh77+bPevXvr559/1ty5c3XeeeeVOdNY3m1xBm9f31vwggsukM1m0xdffOFadvz48RLPLw1WzzzzjCIjI/XAAw+UeAP+77//XrfffrtycnL00EMPuV3IVF7Hjx/Xt99+W+yel1lZWVq8eLEWLFjgtvzw4cMqKChw3RYqOTlZ5557rt59912lpaW5rfvqq6/qtddec51n2aRJEyUlJWnDhg1uh8ed9x81DINv6UGNwzmUQIC65557tHfvXq1Zs0a9e/fWZZddpvPPP182m007duzQ119/rQsuuMB1yE46fT+///u//9OqVas0cOBAXXrppdq/f782bdqkWrVquR2ia9WqlVq3bq20tDTdfPPNSk5OVnp6ujZv3qx27dppx44drnWvvfZaffjhhxo9erT69eunmJgYffvtt9q6davq1aunI0eOFAuhJRk4cKA++eQTrVmzRunp6erevbtsNptWr16t48ePa9y4cWrSpEm5a9WnTx/985//1DfffFPqaQIV3RZnyHnkkUfUrVs33XLLLeUeX0luuOEGffLJJ/r73/+u/v37Kzw8XB999JHOO+881wVKgerPV16fqU+fPho6dKgk6cILL9SiRYs0atQojR49Wm3atFGnTp1ktVqVnp6uTZs2yWKxaOLEiRo8eLCpMX311VcyDKNYoLzyyiuVlJSkN998U3v37lX79u2Vk5OjNWvWSJLrVkKhoaGaOnWq7rrrLg0dOlRXXHGFmjRpov/+97/avHmzzj33XI0dO9bV75NPPqmhQ4dqxIgRuvLKK9W4cWNt3rxZu3bt0i233OJ2sRBQEzBDCQQoq9WqF198UbNnz1b37t317bffatGiRVq2bJkKCgpctwL685WxU6ZM0cMPP6yioiK9+eabOnLkiF5++eUSg9orr7yiAQMG6Mcff9SSJUuUl5en119/3e2+ftLpK81feOEFNW3aVB988IFWrlypgoICPfbYY5o3b54k6fPPP/e4TRaLRS+++KImTpyoqKgoLVu2TKtXr9aFF16ol156SXfffXeFatW8eXPXvQxL+3acim7LPffco3bt2mnjxo0+nT28/PLLNX36dDVt2lQrV67U2rVrNWDAAM2cOdNnz1FZfv31V23durXE//787TPt2rXTf/7zH02YMEEhISFatWqVli5dqoyMDA0dOlQffPCBT0L6hg0b1LJlS9WrV89teXh4uF555RXdddddOnr0qN544w199NFHateunRYvXuw2k9ipUyctW7bMdbP9RYsW6bffftOwYcP09ttvq0GDBq51ExIStGzZMl199dXaunWrFi9erLy8PD388MN6+OGHTW8PEGwsRlWcLATA7/76179qz549rlueAADgK8xQAgAAwBQCJQAAAEwhUAIAAMAUzqEEAACAKcxQAgAAwBQCJQAAAEwhUAIAAMAUAiUAAABMIVACAADAFAIlAAAATCFQAgAAwBQCJQAAAEwhUAIAAMAUAiUAAABMIVACAADAFAIlAAAATCFQAgAAwBQCJQAAAEwhUAIAAMAUAiUAAABMIVACAADAFAIlAAAATCFQAgAAwBQCJQAAAEwhUAIAAMAUAiUAAABMIVACAADAFAIlAAAATCFQAgAAwBQCJQAAAEwhUAIAAMAUAiUAAABMIVACAADAFAIlAAAATCFQAgAAwBQCJQAAAEwhUAIAAMAUAiUAAABMIVACAADAFAIlAAAATCFQAgAAwBQCJQAAAEwhUAIAAMAUAiUAAABMIVACAADAFAIlAAAATCFQAgAAwBQCJQAAAEwhUAIAAMAUAiUAAABMIVACAADAFAIlAAAATCFQAgAAwBQCJQAAAEwhUAIAAMAUAiUAAABMIVACAADAFAIlAAAATCFQAgAAwBSrvwcQiAzDkMNhmO4nJMTik36CHXWgBk7UgRo4UQdq4EQdArsGISEWWSwWj+sRKEvgcBg6evSUqT6s1hDFxdVSdnaubDaHj0YWfKgDNXCiDtTAiTpQAyfqEPg1qFu3lkJDPQdKDnkDAADAFAIlAAAATCFQAgAAwBQCJQAAAEwhUAIAAMAUAiUA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e/c2CgoK/D20CrntttuMa665xti2bZvxww8/GE8++aSRmJho7N+/39i3b5/Rtm1b4/nnnzf27dtnzJs3z2jVqpXx1VdfuR7/0EMPGVdeeaWxbds2Y8eOHcb//d//GUOGDHG1e9NHICksLDQGDhxotGjRwli+fLlhGIZx9OhR45JLLjEefvhhY9++fca7775rtG3b1nj33Xddj/P0vvCmD39btWqV0apVK2PJkiXGwYMHjTlz5hgtW7Y0vv76a6OwsNDo3bu3cffddxvp6enG2rVrjc6dOxv//Oc/XY9fsWKFkZiYaLz33nvG999/bzzwwANG586djSNHjhiGYXjVRyB48cUXjW7duhlffvml8eOPPxoTJ040OnbsaBw6dKjavxeWLFlitGzZ0hg6dKhrWVVtcyDtW0uqw7Zt24yLL77YePnll40DBw4Yn332mdGjRw/joYcecq3ji/2hpz6qSkk1ONPatWuNFi1aGJdffrnb8prwXigoKDD69etnDB482Pjuu++Mb775xvjLX/5i3Hnnna51fLE/9NRHVSJQ+lhBQYGRlJRkvPHGG65lJ06cMBITE40PPvjAjyOrmB9//NFo0aKFkZqa6lrmcDiMK6+80pg5c6bx6KOPGtddd53bY8aOHWvcfvvthmEYRkZGhtGyZUvjs88+c7X/8MMPRosWLYyvv/7aMAzDYx+BZsaMGcYtt9ziFijnzp1rXHbZZUZRUZHber179zYMw7v3hac+/M3hcBiXX3658eyzz7otv/322425c+caH3zwgdGmTRvj+PHjrra33nrL6NChg2sn37t3b+O5555ztRcVFRk9e/Y05s6daxiG4VUfgeDaa681pkyZ4vr55MmTRosWLYw1a9ZU2/dCRkaGMWLECKN9+/ZG37593f54VsU2B8q+taw6jBs3zhg+fLjb+itXrjRat25tFBQU+GR/6E0fla2sGjgdOnTI6NKlizF06FC3QFlT3gvLly832rdvb2RlZbmWffHFF8YVV1xhnDx50jAM3+wPPfVRlTjk7WN79uzRqVOn1LVrV9ey2NhYtWrVStu2bfPjyComLi5Or776qtq2betaZrFYZLFYlJ2drdTUVLdtlaQuXbpo+/btMgxD27dvdy1zatasmRo2bOiqh6c+Asm2bdv09ttv69lnn3Vbnpqaqs6dO8tqtbqWdenSRT/++KMOHz7s1fvCUx/+duDAAf3666/q37+/2/L58+drxIgRSk1NVevWrVWnTh1XW5cuXZSTk6Pdu3fryJEj+vHHH91qYLVa1alTJ7calNVHoKhXr54+/fRT/fLLL7Lb7Xr77bcVHh6uli1bVtv3wnfffaewsDC9//77ateunVtbVWxzoOxby6rD7bffrgkTJrgtCwkJUVFRkXJycnyyP/Smj8pWVg0kyTAMPfTQQ/rrX/+qzp07u7XVlPfChg0b1KVLF9WvX9+1rHv37lq3bp1iYmJ8sj/0po+qRKD0sYyMDEnS2Wef7ba8QYMGrrZgEhsbq549eyo8PNy1bM2aNTp48KC6d++ujIwMNWrUyO0xDRo0UF5eno4dO6ZDhw4pLi5OERERxdZx1sNTH4EiOztbDz74oCZNmlTs9S1tGyTp999/9+p94akPfztw4IAkKTc3V3fccYe6du2q66+/Xp988omkmlEDp4kTJyosLExXXHGF2rZtqxdeeEEvvviimjZtWm3rkJKSolmzZqlJkybF2qpimwNl31pWHVq1aqWWLVu6fi4qKtLChQvVpk0b1a1b1yf7Q2/6qGxl1UCSFi5cqKysLI0dO7ZYW015Lxw4cEDnnnuuXnrpJV111VW6/PLL9eijjyo7O1tS9aqDE4HSx/Ly8iTJLYBJUkREhAoKCvwxJJ/6+uuv9fDDD6t3797q1auX8vPzi22r8+fCwkLl5eUVa5fc6+Gpj0DxxBNPKCkpqdgMnVTyNjh3+AUFBV69Lzz14W85OTmSpAkTJuiaa67RggUL1K1bN40cOVKbNm2qETVw2rdvn2rXrq2XXnpJb7/9tgYOHKjx48dr9+7dNaoOTlWxzcG2b7XZbHrwwQf1/fff6/HHH5ckn+wPvenDn/bs2aPZs2dr2rRpJY6zprwXcnJytGrVKqWnp2vGjBl66qmntH37do0cOVKGYVTLOlg9r4LyiIyMlHT6F9/5b+n0ix8VFeWvYfnEunXrNH78eHXo0EHTp0+XdPqN++fQ5/w5KipKkZGRJYbCM+vhqY9AsGrVKqWmpuqDDz4osb2k7XT+QkdHR3v1vvDUh7+FhYVJku644w4NGDBAknTxxRdr165deu2118pVgz+vEyw1kE7PDIwbN04LFy5Up06dJElt27bVvn37NGvWrBrxXvizqtjmYNq35uTk6O9//7u2bt2q2bNnKzExUVLJ2yiVb3/oTR/+UlBQoPHjx+vee+91m6k9U015L1itVkVHR2vGjBmufWedOnV0/fXX69tvv/XJ/tCbPqoSM5Q+5px6zszMdFuemZmphg0b+mNIPrFkyRLdd999uvzyyzV37lzXp6Szzz67xG2Njo5W7dq11ahRIx0/frzYG/7MenjqIxAsX75cR44cUa9evZSUlKSkpCRJ0uOPP64777xTjRo1KnEbJKlhw4ZevS889eFvzjG0aNHCbfmFF16oX375pUbUQJJ27NihoqIit/OKJaldu3Y6ePBgjanDmapim4Nl35qZmem6jdT8+fPVs2dPV5sv9ofe9OEvO3bs0Pfff6/Zs2e79pOvvPKKfvvtNyUlJSk1NbXGvBcaNWqkZs2aucKkJF100UWSTt8KqDrWgUDpYy1btlRMTIy2bNniWpadna1du3YpOTnZjyOruKVLl2ry5MkaMmSInn/+ebfp9U6dOmnr1q1u62/evFkdOnRQSEiIOnbsKIfD4TqRXDp9bsmhQ4dc9fDURyCYPn26/vOf/2jVqlWu/yRpzJgxevrpp5WcnKzt27e73R9s8+bNatasmerVq+fV+8JTH/7WunVr1apVSzt27HBbvnfvXjVt2lTJycnatWuX69C4dHr8tWrVUsuWLVWvXj01a9bMrQY2m02pqaluNSirj0DgPKcpPT3dbfnevXt1/vnn14j3wp9VxTYHw771xIkTuvXWW3X06FG98cYbxcbli/2hN334S2Jioj7++GO99957rv3kjTfeqAYNGmjVqlVq06ZNjXkvJCcna8+ePW73IN27d68k6bzzzvPJ/tCbPqpUlV9XXgM8//zzRufOnY1169a53R+rsLDQ30Mrtx9++MFo3bq1MWrUKCMzM9Ptv+zsbGPv3r1G69atjWnTphn79u0z5s+fX+yeaWPHjjVSUlKMzZs3u+6ZdubtFbzpIxCdedugw4cPG8nJycaECROM77//3li+fLnRtm1bY8WKFa71Pb0vvOnD31566SUjKSnJ+OCDD9zuQ7l582YjPz/fuPLKK4077rjD2L17t+ueabNmzXI9/u233zYSExONFStWuO6Zdskll7jumeZNH/5mt9uNm266yejbt6+xadMm48CBA8YLL7xgXHzxxcY333xTI94LEyZMcPsdrqptDrR965/rMGHCBKN169bGpk2biu0vbTabYRi+2R966qMq/bkGf/biiy8Wuw9lTXgvHDlyxLj00kuNkSNHGnv37jVSU1ONa665xhg2bJhrHV/sDz31UZUIlJXAZrMZzz33nNGlSxejffv2xl133WX8/PPP/h5Whbz88stGixYtSvxvwoQJhmEYxueff25cc801Rps2bYy+ffsaH374oVsfp06dMiZOnGh06tTJ6NSpkzF27Fjj6NGjbut46iMQnRkoDcMwduzYYdxwww1GmzZtjMsvv9xYvHix2/revC889REIFixYYKSkpBitW7c2rr32WmPt2rWuth9//NG47bbbjLZt2xqXXXaZMXPmTMNut7s9ft68eUaPHj2MxMRE4+abbzZ27drl1u5NH/52/Phx44knnjB69eplJCUlGYMHDza2bNniaq/u74WSQkRVbHOg7VvPrIPNZjPatm1b6v7SOU5f7A+96aOqVCRQVvf3gtOBAweMu+++22jXrp2RnJxsPPzww8aJEyfc1vHF/tBTH1XFYhgBdqM/AAAABJXAOEENAAAAQYtACQAAAFMIlAAAADCFQAkAAABTCJQAAAAwhUAJAAAAUwiUAAAAMIVACQDltGLFCiUkJOiXX37x91BKNWvWLCUkJFT6YwBAIlACAADAJAIlAAAATCFQAkAZHA6H5syZo169eqldu3YaOXKkTpw4Ua4+tmzZooSEBG3atEnDhg1TYmKievXqpWXLlikzM1OjR49WUlKSevbsqYULF7o9NjMzUw8//LB69uypxMREXXfddVq/fr3bOgUFBZoyZYq6deumpKQkPfzwwyooKCg2jtTUVA0dOlTt2rVT586dNWHCBB09erTcNQGAPyNQAkAZpk2bppdeeknXXXedZs+erbPOOkszZsyoUF9jx45VSkqKXnnlFTVr1kyPP/64brnlFl100UWaM2eOEhMTNWXKFO3cuVOSdPjwYV133XVKTU3V/fffr1mzZqlx48YaNWqU3n//fVe/DzzwgN555x2NGDFCM2fO1IkTJ4oF023btmn48OGKjIzUzJkz9cgjj2jr1q265ZZblJ+fX+H6AIAkWf09AAAIVNnZ2Vq8eLFuu+02jR49WpLUvXt3ZWZm6ssvvyx3f4MGDdJtt90mSYqOjtYNN9ygxMRE/e1vf5MktWzZUh9//LG+/vprJSYm6rXXXtPRo0e1Zs0aNW7cWJLUs2dPDR8+XM8995yuueYa7d+/X2vWrNETTzyhm266yTXG/v37a9++fa7nnjFjhpo1a6ZXXnlFoaGhkqR27dqpX79+Wr58uYYMGVLxQgGo8ZihBIBSfPPNNyoqKtLll1/utvzqq6+uUH9JSUmuf9erV0/S6VDnFBcXJ0k6efKkJGnr1q1KSkpyhUmna6+9VllZWfrhhx+UmpoqSUpJSXG1h4SEqE+fPq6f8/LytGPHDvXs2VOGYchms8lms6lJkyZq3ry5Nm7cWKHtAQAnZigBoBTOcyWdQc8pPj6+Qv3FxMQUWxYVFVXm8zdp0qTY8vr160s6PYPqzRizs7PlcDj0r3/9S//617+K9RcREeHdBgBAKQiUAFAKZ0g7cuSILrjgAtfy48ePV8nz16lTR1lZWcWWO5fFxcW5xnj48GGdc845JY6xVq1aslgsGj58uPr161esv7JCLQB4g0PeAFCKpKQkRUZG6qOPPnJb/umnn1bJ8ycnJystLU2//vqr2/L3339f8fHxOu+889SlSxdJKnOMMTExatWqlX744Qe1bdvW9d9FF12kWbNmacuWLZW/MQCqNWYoAaAUtWrV0siRIzVz5kxFRUWpS5cu+vzzz6ssUN522216//33NXz4cI0ePVpnnXWWVq1apc2bN+uZZ55RSEiIzjvvPA0ePFgvvPCCbDabLr74Yr333ntKT09362vs2LG6++67NW7cOF177bWy2+1asGCBduzYoZEjR1bJ9gCovpihBIAyjBgxQo888og++ugj3XvvvUpPT9eECROq5Lnj4+P15ptvqnXr1vrHP/6hv/3tb/r99981Z84cDRo0yLXe448/rrvuuktLlizR6NGjlZ+fr3vuucetr8suu0zz589XRkaGxowZowcffFChoaF67bXX1L59+yrZHgDVl8UwDMPfgwAAAEDw4pA3AFSQ3W6Xp8/kFovFdd9HAKiumKEEgApKSUkpdsHMn3Xu3FmLFy+uohEBgH8QKAGggtLT01VYWFjmOrVq1XK75RAAVEcESgAAAJjCVd4AAAAwhUAJAAAAUwiUAAAAMIVACQAAAFMIlAAAADCFQAkAAABTCJQAAAAwhUAJAAAAU/4fsHZCKdYI4YUAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "matmul_plot = sns.scatterplot(matmul_results_df, x=\"d_model\", y=\"TFLOP/sec/GPU\")\n", + "plt.suptitle(\"Square Matmul TFLOP/sec\")\n", + "matmul_plot.axhline(y=312, color=\"r\", linestyle=\"--\")\n", + "matmul_plot.figure.savefig(\"matmul.png\", dpi=256, bbox_inches=\"tight\")" + ] + }, + { + "cell_type": "markdown", + "id": "a309a6fa-8bd7-4559-b2e1-3774f0f530f8", + "metadata": {}, + "source": [ + "## MLP TP Plots" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "5024162f-4d26-4d0e-a78d-6444e62248d7", + "metadata": {}, + "outputs": [], + "source": [ + "mlp_tp_trial = projects_dict[\"MLP TP Profiling\"].list_experiments()[0].list_trials()[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "10445d10-70ba-4163-bfc4-a14cc3f7b64c", + "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", + "
tp_degreed_modeltime_sTFLOP/sec/GPUTFLOP/sec/GPU_std
0110240.000492139.7606051.070486
1115360.000965160.2972110.191192
2120480.001459188.4338993.754535
3125600.002080206.4862062.993310
4130720.002941210.2913972.333767
..................
1518184320.012830216.6374662.120074
1528189440.013551216.7002563.428361
1538194560.014483213.7898102.577091
1548199680.015056216.6678923.947501
1558204800.015662219.1872254.835044
\n", + "

156 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " tp_degree d_model time_s TFLOP/sec/GPU TFLOP/sec/GPU_std\n", + "0 1 1024 0.000492 139.760605 1.070486\n", + "1 1 1536 0.000965 160.297211 0.191192\n", + "2 1 2048 0.001459 188.433899 3.754535\n", + "3 1 2560 0.002080 206.486206 2.993310\n", + "4 1 3072 0.002941 210.291397 2.333767\n", + ".. ... ... ... ... ...\n", + "151 8 18432 0.012830 216.637466 2.120074\n", + "152 8 18944 0.013551 216.700256 3.428361\n", + "153 8 19456 0.014483 213.789810 2.577091\n", + "154 8 19968 0.015056 216.667892 3.947501\n", + "155 8 20480 0.015662 219.187225 4.835044\n", + "\n", + "[156 rows x 5 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mlp_tp_results_dict = defaultdict(list)\n", + "for group in (f\"tp_degree_{n}\" for n in (1, 2, 4, 8)):\n", + " for m in mlp_tp_trial.iter_metrics(group):\n", + " mlp_tp_results_dict[\"tp_degree\"].append(m.metrics[\"tp_degree\"])\n", + " mlp_tp_results_dict[\"d_model\"].append(m.metrics[\"d_model\"])\n", + " mlp_tp_results_dict[\"time_s\"].append(m.metrics[\"time_s\"])\n", + " mlp_tp_results_dict[\"TFLOP/sec/GPU\"].append(m.metrics[\"tflop_s_gpu\"])\n", + " mlp_tp_results_dict[\"TFLOP/sec/GPU_std\"].append(m.metrics[\"tflop_s_gpu_std\"])\n", + "mlp_tp_results_df = pd.DataFrame.from_dict(mlp_tp_results_dict)\n", + "mlp_tp_results_df" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "ed6b17bc-5ddf-470c-9aaa-cfc0529367fb", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAApQAAALQCAYAAAAuBuBGAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd3QUVR/G8e/WbDoJkNB77x3pRaUoRUQBBVTQVxRQxN5FpYgFxd5QRIqiiIIgCEgJvffQWwgQShLSts+8fwzZsCSBJJuQAL/POTmQ3dnduzczs8/euUWnqqqKEEIIIYQQeaQv7AIIIYQQQogbmwRKIYQQQgjhEwmUQgghhBDCJxIohRBCCCGETyRQCiGEEEIIn0igFEIIIYQQPpFAKYQQQgghfCKBUgghhBBC+EQCpRBCCCGE8IkEypvcZ599Rs2aNalZsyZffvnlVbcdO3asZ9uTJ096bu/cuTM1a9bM0esNHjzY8xyX/9SrV4+2bdsycuRItm/fftXnePnll7N8jqx+Bg8eDMCGDRtytP3UqVMBOHnypNfjc8rlcvHrr7/y0EMPcdttt9GgQQO6dOnCc889x5YtW7J8zB9//JFlWerUqUOzZs3o168fP//8M263O8vHf/XVV7Rq1YqitKhVly5dmDhxYqbbN2/ezCuvvEL37t1p3LgxjRs3pmfPnrz//vvExcVl2j67v1vt2rVp3Lgx99xzD19++SU2m83rcen72eX76ZXS6/2zzz7L03tM3w+jo6Pz9PirSU5OZvr06Xl6bPp7T0pKyudS5Ux6vaYfS0XVxIkTadasWWEX47oq7H0jN+Li4mjWrFm25+DTp0/zwgsv0K5dOxo3bsyDDz7I2rVrs9w2OjqaJ554gmbNmtGsWTMeeugh1qxZk+W2brebn3/+mZ49e9KgQQM6duzIK6+8kuX5SeSOsbALIK6fJUuWMHz48CzvU1WVf//9N99e66GHHiIkJMTzu9Pp5NixYyxdupTly5fz1Vdf0b59+ywfe8cdd1C2bFmv23766SeSk5MZOXKk1+1XblerVi3uuOOObMvVqFGjXL6TDKdOnWLYsGEcOHCAMmXKcOeddxIaGkpMTAxLly7l77//pn///rz++uuYzeZMj2/RogUtWrTw/O52u7l48SJLlixh7Nix7Nixgw8//DDT41avXk3r1q3R6XR5Lnt+iomJ4fjx47Rt29Zzm91u5+2332bOnDlYLBZatWpFp06dUBSFXbt2MWXKFGbOnMnkyZPp0KFDpue88u+mKArJycmsWrWKyZMns27dOqZOnYrBYLgu77Ggde3alZIlSzJo0KDCLkqu1a5dm5EjR/p0LBW0hQsXMnXqVAIDAwu7KCIbb731FsnJyVned/78eR588EHOnTtHz549CQ4OZsGCBQwdOpQvvviC22+/3bPtxo0b+d///ofdbqdz586ULVuWqKgoHn30Ud544w0GDhzo9dwvvfQS8+fPp27dugwcOJCjR4/yxx9/sHHjRubOnev1uSVyRwLlLaJkyZLs3buXkydPUq5cuUz3b9u2jbi4OAICAkhLS/P59R5++OEsX2f+/Pk8//zzjB07NtsAe8cdd2QKhXPnziU5OZmnnnrqqq9bu3bta26TFykpKTz88MPExMQwatQoHn/8cYzGjMMnPj6eZ599ll9//RWr1coHH3yQ6TlatGiRZdmeeuopevfuzfz58xkwYIBXq0pKSgrbt29n7Nix+f6e8ioqKgqLxeJVztdff5158+bRrl07JkyYQMmSJb0es3HjRoYPH87o0aP5559/iIyM9Lo/u7+bzWajf//+bNy4kb///pvevXsXzJu6zi5cuJCpjm4UtWvXpnbt2oVdjGxNnTqVDz74AEVRCrsoIhvz589n+fLl2d4/efJkTp06xddff02nTp0AePTRR+nbty9vv/027dq1w2w243a7efXVV7HZbEyePJlu3boB2nnjscceY8KECbRp04ZKlSoBsGjRIubPn8/dd9/Nhx9+iF6vXaSdMmUK77//PtOmTcvUaCFyTi553yLSv9EtXbo0y/sXL15McHBwgV8i6tGjB6VKleL48eMcPXq0QF8rP33yySecOHGCxx9/nOHDh3uFSYDw8HC+/fZbqlatyrx581i5cmWOnzs8PJx7770XgFWrVnndt379elwuF23atPH9TeST1atX06xZM/z8/AAtYM6bN8/TrSKroNSiRQteeuklUlNTmTlzZo5fy2KxeFrxrqwbIS4XExPD4MGDmTBhAjVq1CAsLKywiySyEB8fz7hx47K8UgGQmprKn3/+Sd26dT1hEiAyMpLBgwcTFxfnORfs2rWLmJgY2rZt6wmToJ03nn32WZxOp1fXkunTpxMYGMibb77pCZMADzzwAL1796Z48eL5/XZvKRIobxG33XYbISEh2bYK/vvvv3Tu3BmTyVSg5dDpdERERACQmJhYoK+VX9LS0pgzZw4BAQE8/vjj2W5nNpt55plnAJg1a1auXiO9xe7KOomKiqJmzZqeOnO5XHz++ef07NmTRo0a0aJFCx599FHWrVuX6TlTUlL48MMPueOOO6hXrx7t2rXjrbfe4sKFC5m2tVqtfPrpp3Tr1o2GDRvSuXNn3n77beLj4722czqdrF+/nnbt2nlu++WXXwCtpTWrS/3pevXqRffu3alXr17OKuWSwt5fEhMTeeWVV2jWrBlNmjThiSeeyLJfZXx8PBMnTqR79+40bNiQhg0bcvfdd/P111/jcrmAjD6jAPv27cvUx/PkyZO89tprtG/f3vP4H374AafTmen14uLiePHFF2nZsiWNGjXigQceyHI/yI2///6bAQMG0Lx5cxo3bkzfvn2ZOXOmV//dK/tQXt5PO7ufy+3Zs4fhw4fTsmVLGjRoQO/evZk1a5bXa6T3cb7Wzx9//OF5zKZNm9i2bRtDhw7ll19+ISAgwKe6SHf8+HFGjRpFp06dqFevHp07d2bMmDGcO3cu07Y5eW/pNm/ezJAhQ2jSpAmtW7dm/PjxHD582Kd+v9lZt24dQ4YMoWnTpjRq1Ij+/fuzaNGiTNvVrFmTl19+ma1btzJ48GAaN25M8+bNeeaZZ7z6K+fl75Pu3XffBeC1117Lsqw7d+7E4XDQsmXLTPel37Zx40ZPOSDrrkzp+93WrVsBLahu2bKFli1bUqxYMa9tAwICeP/993nggQeyLJPIGbnkfYswmUx07tyZefPmcf78eUqUKOG5b+fOnZw6dYpu3brx+++/F2g5FEXxnASuvOxZVG3fvp20tDTatm1LUFDQVbdt3749FouF1atXY7PZsFgsOXqNEydOABnhKd3q1avp0qWL5/d3332XX375hRYtWtC+fXuSk5NZuHAhjz76KD/++KPnhJucnMyDDz7IgQMHaNWqFV26dOHkyZPMnj2bqKgofvnlF89rWa1WHnjgAaKjo6lfvz4DBgzgxIkTzJw5k82bNzNr1izP+96+fTupqameFlOHw0FUVBRms9mrT2VW/Pz8+OSTT3JUHzmpm+vlhRdeQK/X07dvX86ePcu///7L+vXrmT59uiccJycn069fP06fPk3nzp254447iI+PZ8mSJXz88cdcvHiRl156ibJlyzJy5Eg+//xzSpQowYABAzz9ag8cOMDgwYO5ePEiHTt2pHLlymzcuJGJEyeyf//+TIOgHn74YYoVK8a9997L2bNn+eeff3j00Uf57bffqFu3bq7f54IFC3juueeoVKkSffr0Qa/Xs2zZMt5++20SEhIYMWJElo9r0aJFlpcJt2zZwrp162jcuLHntpUrVzJy5EhMJhNdunQhPDycqKgoxowZw969ez1hIyQkJEeXHi+/9N6wYUP++ecfypcvn9u3nq34+HgeeeQREhIS6Nq1KxEREezfv59Zs2axYcMG5s2b5/kSntP3BrBixQrPtt26dcPf35+5c+dec8BiXvz222+88cYbhIeHc9dddxEQEMCyZcsYNWoUo0eP5oknnvDafs+ePTz00EM0bdqUBx54gJ07d/LPP/+we/duFi5ciNlsztPfB7QrZAsXLuT999/PtgU5/XivUKFCpvvS+8wfO3YMwPMF1uFwZNo2JSUFgNjYWAAOHz6MoihUr16d7du3M3nyZLZv347ZbOb222/n+eefJzw8/JrvSWRPAuUtpEuXLvz5558sW7aM/v37e25ftGgRQUFBtG3btsAD5bRp04iPj6du3bqUKVMm358/Ojo622/3d9xxR576fqVfmq9cufI1t7VYLJQpU4YjR45w5swZT9+dq4mNjeX3339Hp9Nx5513em4/duwYJ0+e9LQGpqSkMHv2bJo3b87PP//s2e7+++/nvvvuY8aMGZ5AOWnSJA4cOMCbb77p1Sl92bJlDB8+nHHjxjF58mQAvv32W6Kjo3n44Yd55ZVXPIN/vvnmGyZNmsRvv/3GkCFDAC3gRkZGUr16dQDOnDmD3W6natWq+Pv7X/O95tbFixf58ccfAbyC9fXk7+/Pb7/95mnVWLlyJcOGDWPs2LGe1tlZs2YRExPD2LFjuf/++z2PHTlyJF26dGH+/Pm89NJLlCtXjqeeesoTKC/vN/r2229z8eJFPv30U897VVWVxx57jD///JOHHnrIKyjWq1ePL774whNo6tevz4QJE5g7d26eAuWUKVMICAhgzpw5ni8QI0eOpFu3bkyfPp3hw4dnOTCsZcuWmVqTjh07xrRp0yhZsqRnP7Narbz88ssEBwcze/ZsTx/r559/nmeeeYbZs2dzxx130KFDB0JCQnLdF7pq1aq5fs/XsnDhQk6dOsX48ePp27ev5/Z33nmHGTNmsGbNGjp27Jir9+ZyuRgzZgwmk4lZs2ZRq1YtAB555BGvfSc/nDlzhnfeeYcqVaowY8YMT4gbPXo0jzzyCJMnT6Zz587UqFHD85gDBw7wwgsv8NhjjwEZ++Dq1atZv3497du3z9PfJykpiTFjxtCuXTt69+6d7Uj09CsRWQ2OCQ4OBvAM5knfz5cvX86oUaO8uiItW7YMyAiWZ8+eBbTAPGXKFBo1akS/fv3YvXs3c+bMYcuWLfz++++e1xC5J4HyFtK2bVsCAgL4999/vQJl+uXuq12uzK2ffvrJ64RgtVrZtWsXGzduJCAggDFjxuTba11u37597Nu3L8v7ypYtm6dAmX7yyumI0dDQUAASEhK8AuXGjRu9wq7b7SY2Npb//vuPlJQUHnvsMa/Lg6tXr8bf39/Tr1VRFFRV5fTp05w7d87TV7F+/fosXbqUUqVKAdpl8T///JPq1atnGuF4++2306RJE5YsWUJKSgpBQUEsWLCAoKAgnnvuOa/AMGjQIJKSkqhWrZrntqioKK+WyPTL51md/BVF4Ysvvsiyjq78MLryi4CiKJw9e5bly5dz4cIFunfv7tWf6noaPny41yWyDh060KZNG1avXu0Z5Na2bVtCQkK45557vB5bunRpypcv72lRyc6ZM2fYvHkzbdq08QrOOp2OZ599lkaNGmU6Ph9//HGvLiqdO3dmwoQJV51K6WpUVcVms3Hw4EFPq2JQUBC///47ISEhOZ5lICUlhSeffBKr1crXX3/tuRLx33//ER8fz4svvug1YE+v1/Pcc8+xePFi5syZk23fusKQPrBnz5493HPPPZ5ZBkaPHs2TTz7pOQZz8962bt3K6dOneeCBBzxhErQWuSFDhvDxxx/nW/nnzZuHw+Hg6aef9moRtFgsPP300wwZMoS5c+fy0ksved330EMPeX7X6XS0a9eO1atXe1r78mLChAmkpqby9ttvX3W79O4dWX0epd9mt9sB7ZzetWtXFi9ezOjRo3n22WcpUaIEK1asYNKkSfj7+3taL9MHm65evZonnniC0aNHe573vffe48cff+Szzz7j1VdfzfN7vNVJoLyF+Pn50bFjR5YsWUJycjLBwcHs2bOHmJgYXnnllXx9rWnTpnn9brFYiIiI4L777mPo0KEF0poA0KdPH9577718fc70sJR+ErsWq9UKkOnyycaNGz19fwCMRiMhISE0atSIvn37ctddd3ltnz74Jf0kGhISwl133cWCBQvo1KkTjRs3pn379nTq1Mkr9B09epS0tDTcbneWrbV2ux23283+/fupU6cOx48fp3nz5p5BNukCAwN54YUXPL/Hx8ezd+9eT8sFZITnrFobFEXh888/z7KOrgyUV34RMBgMBAcHU716dZ566imvL0BArqZQ8nW6pSZNmmS6rUGDBqxevZp9+/ZRrlw56tSpQ506dUhNTWXHjh0cP36cY8eOsWvXLo4fP57tHKPp9u/fD2TdF6xu3bpZtjhWrFjR6/f00JuamprDd+atf//+vPXWWwwYMICaNWvSvn17OnToQNOmTb0GMFyNoig899xzHDlyhLfeeoumTZt67tu9ezeghbOs9kuDweDZB5KSkvjpp5+u+Xp5veqQU127duWLL75gxowZLFy4kLZt23rq5fLBZ7l5bwcOHAC0L4JXyqrfoC/Sy7Vu3ToOHjzodV96wLryC3iZMmUyhbn0Vrv0cJbbv8+aNWv4448/eO211zJN9Xal9G5CWfUbTn/9y/vHjh07loSEBP7991/PGAGTycRLL73E7NmzPSE4fR8uXrx4psv1Tz/9NL/++iv//POPBEofSKC8xXTp0oWFCxeyfPlyevXqxeLFiwkMDPQaZJEfli1bluW0QTei9L4812plAq118Pjx4xiNxkx9REeOHJnjy0QOh4MNGzYwatQor9snTpxIvXr1PPOmbdy4kQ8//JB69eoxduxYateu7Ql3R44cyTbQgXY5OX3ba/UNBVizZg06nY5WrVp5bitdujQGg4HTp0/jcDi8PoiMRqMnKKXr3bt3li3Iuf0ikF7e9MEuWUmfDD0n7+1qshr5md5anf6hbLfbmTRpkmfaKND6CDdv3pywsLAsB3Bc7uLFi7ku65VfAHw1YMAAihcvzrRp09iyZQv79+/nu+++IzIykpdffjnTF56sTJo0iRUrVtC3b18efPBBr/vSW/oXLFiQ7ePT6yEpKemq+266vF51yKnIyEh+//13vvrqK5YtW8b8+fOZP38+JpOJe++91zPnbG7eW/q2WQ0ayu+R6emvld4142rlSpdVy2D6l7L0wUW5+ftUqFCBN954g0aNGuVo3tX0L6lZzVGZftvlx0lISAjTpk1j7dq17Nmzh6CgIDp27EiZMmX44osvPOMF0kNxjRo1Mg0+DQgIoGLFikRHR2O32/P92LpVSKC8xXTo0AGLxcKSJUs8gbJTp075ern7ZtOiRQtCQkLYsGGDp2U3O2vXrsVqtXrqOa+2bt1KWlpapqBvMpkYOnQoQ4cO5dSpU6xZs4ZFixaxevVqhg0bxrJlyzxhp3fv3rz//vtXfZ30E3R2rVppaWmeD77Vq1dTr149rw89f39/WrduTVRUFGvWrLlul6XTy3D+/Pls+6mmr3zh64d0cnJypqCX3h8r/cPvvffeY+bMmXTt2pWBAwdSs2ZNT4th9+7drxko0+s4q7+Doig4HA6f9qecuvPOO7nzzjtJSkpiw4YN/Pfff8yfP5/nnnuOatWqefW1u9Lff//Nd999R4MGDbLs0pL+HqdOner1pSQr5cqVy/RlpLCUL1+e8ePH43a72b17N1FRUfzxxx/8+uuvBAcH88ILL+TqvaVf8chqn7hyVgVfpZdr6dKl+TpYKTd/nw0bNhAbG0tsbGyW4X/jxo3UrFnT86Uy/XjOqutG+m1X9mfX6XS0adPGa3q12NhYEhISPN030lv0s2r5BO3LqdFoLPCZTm5mMm3QLSYgIIC2bdsSFRXFzp07OXbsGN27dy/sYhVpZrOZ/v37k5aWxqeffprtdk6n0zOK+cpLtLm1evVqSpcu7dU1ICYmhkmTJnkmBC5Tpgz3338/U6ZM4bbbbiMuLo6TJ09SuXJlzGYze/bsyXK6kqlTp/Lll1+SkJBAcHAwpUuXJjo6OtNISYfDQZs2bRg6dCiqqrJmzZos58NMn2rjo48+uma3gPyabDr90vDmzZuz3SZ9upCGDRv69Fq7du3KdNv27dvR6XTUqVMH0MJU8eLFmTx5ste0JDabjVOnTgFcdenM9L6zO3fuzHTftm3baNSoEV999ZVP7+NqHA4HX331lWcqoJCQEO68804mTJjAk08+iaIobNu2LdvH7969m9dee43ixYvz2WefZfkFNf09pl+GvVxiYiLjxo3jr7/+yp83lE+WLVvGmDFjSElJwWAw0LBhQ0aOHMmMGTMAPMut5ua9pV/qzmpE9549e/K1/OnlymofPnbsGBMnTuS///7L19e8UvrMBlf+/O9///O6P30xi7p162KxWNi0aVOm50rvMpQeEp1OJ3feeWeWI86XLFkC4OnzXaFCBUqWLMnu3bs9A3XSJSUlceLECapVq5bj7h0iM6m5W1CXLl2wWq2MGzeOgICAfL/cfTMaOXIkVapUYdq0aUyePDnTpdaEhASeeuop9uzZQ48ePbyWBsuL1atXZwpvFouF7777jsmTJ3uFP4fDwblz5zCbzZQsWRI/Pz/uuusuDh065BkhnW7Dhg28//77zJkzx9O61qtXL5KTkzMNoJk2bRppaWm0atWK/fv3c+7cuSynBrr99tu59957OXjwIEOHDs2y4/7Zs2d57bXXOHDgQL4sIdm5c2eCgoKYMmUKe/fuzXT/woUL2bhxI82aNcvRSPur+eabb7zWEp83bx47duzw6kfn5+eH3W736kvqdrsZN26c57GXt4yYTCav38uXL0/jxo1ZvXo1UVFRntsVReG7775DVdUCndzebDbz999/M3nyZGJiYrzuS/97Zjcrw/nz5xkxYgRut5tPP/3UMzjsSnfeeSdBQUF8//33mRY1+OCDD5g2bZpnypii4siRI8yaNSvTvLJX1klu3luDBg2oWbMmixYt8gpNZ8+e5fvvv8/X8vfq1QuDwcAnn3zi1SLqcrl49913+eGHHwp8ftf0mQ2u/Emf07ds2bI89dRTnkAZEBDAnXfeybZt2zwjtUG74vDzzz8TERFBx44dAe04KlWqFKtWreL48eOebU+cOMHXX39NiRIlPItG6PV67r//fmw2W6YpuCZNmoTdbvcayS9yTy5534LSJzDfvn07PXr0yHF/kcGDB2d739dff31DrpsbHR2d7fuqUKEC48aNA7Qw9/PPPzNixAi+/PJL/vrrL9q2bUuxYsWIjY1l5cqVJCcnc++99/LWW2/5VKbz58+zb98+hg0b5nV7yZIlefjhh/nxxx/p0aMHHTp0QK/XExUVxeHDhxk+fLjn0uxLL73Etm3bmDhxIsuWLaNBgwbExcXx77//YjQaGT9+vOeb+LBhw1ixYgVff/01mzZtomHDhhw5coQVK1bQoEEDHn74YX766SeCgoKyXb/5nXfeITQ0lKlTp3LnnXfSsmVLqlevjsFg4MCBA2zYsAGn00mVKlWuOcozJ4oXL84777zDSy+9RL9+/Wjfvj1VqlTB5XKxc+dOtmzZQtmyZTMtWZk+mCA4OJhHHnkkR6+VnJxM79696dy5s2fd9pIlS/LGG294tunZsyc//PADffv25Y477sDlcrF69WqOHj1KeHg48fHxJCYmeubSjIiI8Axc6dChg2ci+UGDBjFs2DDPevbr169n7969PPTQQzRo0MDneruaZ599lhEjRtCnTx+6detGaGgou3fvZv369bRo0SLbQPvCCy9w5swZWrduzY4dO1i/fn2m1tg+ffpQrlw5xo4dy/PPP0+fPn244447iIiIYNOmTezcuZP69eszdOjQAn2P6ZYuXUp0dPQ1B/X069eP2bNn8+GHH3ouzV64cIFFixZ5LXQQEhKSq/c2ceJEBg8ezJAhQ+jatSvBwcEsXbo0y/kUfVGpUiVeeOEF3nvvPXr06EHnzp0JDQ1l1apVHD58mE6dOtGrV698fc388Oyzz7JmzRqefvpp7r77bsLCwliwYAEXLlzg888/92oBf+mllxgwYAD9+/enR48eOBwOFi5ciN1u55tvvvGazmzYsGGsXbuW2bNns3//fpo2bcqOHTvYsmULTZs2zdTvV+SOBMpbUHBwMK1atWLVqlV07do1x4+7fITyla41irWoSk5OzvZ9XTlyuUSJEsyYMYN///2X33//nZUrV5KQkEBERAQdOnSgf//+nkmqfbF69Wp0Oh2tW7fOdN8LL7xAxYoV+e2335g7dy5ut5tq1arx3nvv0adPH8924eHhzJ49m2+++YYlS5bw888/Ex4eTufOnRk+fLjXdCWBgYHMnDmTL7/8kkWLFrFjxw7CwsIYNGgQzzzzDGazmdWrV3PbbbdlWnIynclk4uWXX6Z3797MmTOHDRs2sGvXLhwOByVLlqRr1650796dzp0759slpbvvvpvKlSszffp0Nm7cyNq1azEajZQuXZqRI0cycODATCPt0wcTlC1bNseB8quvvmLy5Mn88ssvGI1G7r77bp577jmvFrvRo0cTGBjIvHnzmDlzJuHh4VStWpXXX3+dw4cPM378eFauXOmZZ/DNN99k7NixzJkzB5fLRefOnalZsya//fYbn332GWvWrCElJYVy5crxyiuveE3jUlBuv/12pkyZwnfffcfy5ctJSkqiTJkyjBgxgv/973/Z/t3SW4bWrl3L2rVrs9ymRYsWlCtXju7du1OqVCm++eYboqKisFqtlC1bluHDh/Poo49ety+lS5cuZe7cudcc1BMaGsr06dP56quvWLNmDevXrycoKIj27dszcuRIz3ysQK7eW+3a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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mlp_tp_plot = sns.lineplot(mlp_tp_results_df,\n", + " x=\"d_model\",\n", + " y=\"TFLOP/sec/GPU\",\n", + " hue=\"tp_degree\",\n", + " palette=[\"blue\", \"orange\", \"purple\",\n", + " \"black\"])\n", + "plt.suptitle(\"MLP TFLOP/sec/GPU, batch_size=1, seq_len=4096\")\n", + "mlp_tp_plot.axhline(y=312, color=\"r\", linestyle=\"--\")\n", + "mlp_tp_plot.figure.savefig(\"mlp_tp.png\", dpi=256, bbox_inches=\"tight\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/blog/tp/requirements.txt b/blog/tp/requirements.txt new file mode 100644 index 0000000..2de173a --- /dev/null +++ b/blog/tp/requirements.txt @@ -0,0 +1,167 @@ +analytics-python==1.4.post1 +anyio==4.4.0 +appdirs==1.4.4 +appnope==0.1.4 +argcomplete==3.4.0 +argon2-cffi==23.1.0 +argon2-cffi-bindings==21.2.0 +arrow==1.3.0 +asttokens==2.4.1 +async-lru==2.0.4 +attrs==23.2.0 +azure-core==1.30.2 +azure-storage-blob==12.20.0 +Babel==2.15.0 +backoff==1.10.0 +bcrypt==4.1.3 +beautifulsoup4==4.12.3 +bleach==6.1.0 +boto3==1.34.135 +botocore==1.34.135 +cachetools==5.3.3 +certifi==2024.6.2 +cffi==1.16.0 +charset-normalizer==3.3.2 +comm==0.2.2 +contourpy==1.2.1 +cryptography==42.0.8 +cycler==0.12.1 +debugpy==1.8.2 +decorator==5.1.1 +defusedxml==0.7.1 +determined==0.33.0 +docker==7.1.0 +einops==0.8.0 +executing==2.0.1 +fastjsonschema==2.20.0 +filelock==3.14.0 +fonttools==4.53.0 +fqdn==1.5.1 +fsspec==2024.5.0 +gitdb==4.0.11 +GitPython==3.1.43 +google-api-core==2.19.1 +google-api-python-client==2.134.0 +google-auth==2.30.0 +google-auth-httplib2==0.2.0 +google-cloud-core==2.4.1 +google-cloud-storage==2.17.0 +google-crc32c==1.5.0 +google-resumable-media==2.7.1 +googleapis-common-protos==1.63.2 +h11==0.14.0 +httpcore==1.0.5 +httplib2==0.22.0 +httpx==0.27.0 +idna==3.7 +iniconfig==2.0.0 +ipykernel==6.29.4 +ipython==8.24.0 +ipywidgets==8.1.3 +isodate==0.6.1 +isoduration==20.11.0 +jedi==0.19.1 +Jinja2==3.1.4 +jmespath==1.0.1 +json5==0.9.25 +jsonpointer==3.0.0 +jsonschema==4.22.0 +jsonschema-specifications==2023.12.1 +jupyter==1.0.0 +jupyter-console==6.6.3 +jupyter-events==0.10.0 +jupyter-lsp==2.2.5 +jupyter_client==8.6.2 +jupyter_core==5.7.2 +jupyter_server==2.14.1 +jupyter_server_terminals==0.5.3 +jupyterlab==4.2.3 +jupyterlab_pygments==0.3.0 +jupyterlab_server==2.27.2 +jupyterlab_widgets==3.0.11 +kiwisolver==1.4.5 +lomond==0.3.3 +MarkupSafe==2.1.5 +matplotlib==3.9.0 +matplotlib-inline==0.1.7 +mistune==3.0.2 +monotonic==1.6 +mpmath==1.3.0 +nbclient==0.10.0 +nbconvert==7.16.4 +nbformat==5.10.4 +nest-asyncio==1.6.0 +networkx==3.3 +notebook==7.2.1 +notebook_shim==0.2.4 +numpy==2.0.0 +overrides==7.7.0 +packaging==24.0 +pandas==2.2.2 +pandocfilters==1.5.1 +paramiko==3.4.0 +parso==0.8.4 +pathspec==0.12.1 +pexpect==4.9.0 +pillow==10.3.0 +platformdirs==4.2.2 +pluggy==1.5.0 +prometheus_client==0.20.0 +prompt_toolkit==3.0.45 +proto-plus==1.24.0 +protobuf==5.27.2 +psutil==6.0.0 +ptyprocess==0.7.0 +pure-eval==0.2.2 +pyasn1==0.6.0 +pyasn1_modules==0.4.0 +pycparser==2.22 +Pygments==2.18.0 +PyNaCl==1.5.0 +pyOpenSSL==24.1.0 +pyparsing==3.1.2 +pytest==8.2.1 +python-dateutil==2.9.0.post0 +python-json-logger==2.0.7 +pytz==2024.1 +PyYAML==6.0.1 +pyzmq==26.0.3 +qtconsole==5.5.2 +QtPy==2.4.1 +referencing==0.35.1 +requests==2.31.0 +rfc3339-validator==0.1.4 +rfc3986-validator==0.1.1 +rpds-py==0.18.1 +rsa==4.9 +ruamel.yaml==0.18.6 +ruamel.yaml.clib==0.2.8 +s3transfer==0.10.2 +seaborn==0.13.2 +Send2Trash==1.8.3 +setuptools==70.1.1 +six==1.16.0 +smmap==5.0.1 +sniffio==1.3.1 +soupsieve==2.5 +stack-data==0.6.3 +sympy==1.12.1 +tabulate==0.9.0 +termcolor==2.4.0 +terminado==0.18.1 +tinycss2==1.3.0 +torch==2.3.0 +tornado==6.4.1 +tqdm==4.66.4 +traitlets==5.14.3 +types-python-dateutil==2.9.0.20240316 +typing_extensions==4.12.0 +tzdata==2024.1 +uri-template==1.3.0 +uritemplate==4.1.1 +urllib3==2.2.2 +wcwidth==0.2.13 +webcolors==24.6.0 +webencodings==0.5.1 +websocket-client==1.8.0 +widgetsnbextension==4.0.11 diff --git a/blog/tp/test_dot_product_distributed.py b/blog/tp/test_dot_product_distributed.py new file mode 100644 index 0000000..eff58a1 --- /dev/null +++ b/blog/tp/test_dot_product_distributed.py @@ -0,0 +1,65 @@ +""" +A sharded dot-product with intermediate activation function computed over multiple processes. Uses +CPU, the gloo backend, and multi-processing, so that the code can run anywhere. +""" + +import os +from concurrent.futures import ProcessPoolExecutor + +import torch +import torch.distributed as dist + +MASTER_ADDR = "127.0.0.1" +MASTER_PORT = 29500 +WORLD_SIZE = 4 +D_MODEL = 128 + +# Environment variables expected by torch.distributed. +os.environ["MASTER_ADDR"] = MASTER_ADDR +os.environ["MASTER_PORT"] = str(MASTER_PORT) +os.environ["WORLD_SIZE"] = str(WORLD_SIZE) + + +def compute_dot_product(rank: int): + # More torch.distributed env vars. + os.environ["RANK"] = os.environ["LOCAL_RANK"] = str(rank) + + assert ( + not D_MODEL % WORLD_SIZE + ), f"Choose D_MODEL to be divisible by WORLD_SIZE {D_MODEL % WORLD_SIZE=}." + act_fn = torch.nn.GELU() + + # Setup: populate the same tensors on all devices. The full tensors will be used to check + # correctness. + torch.manual_seed(42) + a = torch.randn(D_MODEL) + b = torch.randn(D_MODEL) + + # Each rank uses a different shard for the sharded dot-product + a_sharded = a.reshape(WORLD_SIZE, D_MODEL // WORLD_SIZE)[rank] + b_sharded = b.reshape(WORLD_SIZE, D_MODEL // WORLD_SIZE)[rank] + + # Compute the dot-product via collectives. + + # Each rank first computes their local dot-product using the available shards: + c = a_sharded @ act_fn(b_sharded) + + # The computation is completed by summing over processes: + dist.init_process_group(backend="gloo") + dist.all_reduce(c) + + # Test correctness: + torch.testing.assert_close(c, a @ act_fn(b)) + return f"Correct results on {rank=}" + + +def run(): + with ProcessPoolExecutor(max_workers=WORLD_SIZE) as pool: + ranks_list = [r for r in range(WORLD_SIZE)] + results = pool.map(compute_dot_product, ranks_list) + for r in results: + print(r) + + +if __name__ == "__main__": + run() diff --git a/blog/tp/test_dot_product_local.py b/blog/tp/test_dot_product_local.py new file mode 100644 index 0000000..8d9f43e --- /dev/null +++ b/blog/tp/test_dot_product_local.py @@ -0,0 +1,32 @@ +""" +Demonstrating the equivalence of a basic dot product with intermediate activation function and a +sharded-version of the same calculation. +""" + +import torch + +D_MODEL = 128 +RANKS = 4 + +if __name__ == "__main__": + a = torch.randn(D_MODEL) + b = torch.randn(D_MODEL) + + act_fn = torch.nn.GELU() + # The dot-product, different ways + dot_0 = a @ act_fn(b) + dot_1 = (a * act_fn(b)).sum() + dot_2 = torch.einsum("i, i", a, act_fn(b)) + + a_sharded = a.reshape(RANKS, D_MODEL // RANKS) + b_sharded = b.reshape(RANKS, D_MODEL // RANKS) + + # More equivalent dot-products, using the sharded tensors. + dot_3 = (a_sharded * act_fn(b_sharded)).sum() + dot_4 = (a_sharded @ act_fn(b_sharded).T).trace() + dot_5 = (a_sharded.T @ act_fn(b_sharded)).trace() + dot_6 = torch.einsum("ij, ij", a_sharded, act_fn(b_sharded)) + + for dot_prod in (dot_1, dot_2, dot_3, dot_4, dot_5, dot_6): + torch.testing.assert_close(dot_0, dot_prod) + print("Correct results") diff --git a/blog/tp/test_mlp_tp.py b/blog/tp/test_mlp_tp.py new file mode 100644 index 0000000..cc9ea5b --- /dev/null +++ b/blog/tp/test_mlp_tp.py @@ -0,0 +1,92 @@ +""" +Testing the correctness of the TP implementation. Uses CPU, the gloo backend, and multi-processing, +so that the code can run anywhere. + +""" + +import os +from concurrent.futures import ProcessPoolExecutor + +import torch +import torch.distributed as dist + +import layers + +MASTER_ADDR = "127.0.0.1" +MASTER_PORT = 29500 +WORLD_SIZE = 4 +BATCH_SIZE = 2 +SEQ_LEN = 64 +D_MODEL = 128 + +# Environment variables expected by torch.distributed. +os.environ["MASTER_ADDR"] = MASTER_ADDR +os.environ["MASTER_PORT"] = str(MASTER_PORT) +os.environ["WORLD_SIZE"] = str(WORLD_SIZE) + + +def test_mlp(rank: int): + # More torch.distributed env vars. + os.environ["RANK"] = os.environ["LOCAL_RANK"] = str(rank) + + assert ( + not D_MODEL % WORLD_SIZE + ), f"Choose D_MODEL to be divisible by WORLD_SIZE {D_MODEL % WORLD_SIZE=}." + + # Create two sets of equivalent inputs, both requiring gradients. + torch.manual_seed(42) + inputs = torch.randn(BATCH_SIZE, SEQ_LEN, D_MODEL, requires_grad=True) + inputs_tp = inputs.detach().clone().requires_grad_() + + # Create TP and non-TP MLP layers + dist.init_process_group(backend="gloo") + mlp = layers.MLP(D_MODEL) + mlp_tp = layers.MLPTP(D_MODEL) + + # Give the TP model the same weights as the non-TP model: + with torch.no_grad(): + mlp_tp.lin_0.weight.data = mlp.lin_0.weight.data.tensor_split(WORLD_SIZE, dim=0)[rank] + mlp_tp.lin_0.bias.data = mlp.lin_0.bias.data.tensor_split(WORLD_SIZE, dim=0)[rank] + mlp_tp.lin_1.weight.data = mlp.lin_1.weight.data.tensor_split(WORLD_SIZE, dim=1)[rank] + mlp_tp.lin_1.bias.data = mlp.lin_1.bias.data + + # The outputs should be the same: + outputs = mlp(inputs) + outputs_tp = mlp_tp(inputs_tp) + with torch.no_grad(): + torch.testing.assert_close(outputs, outputs_tp) + + # Perform a backwards pass on a simple loss function. + outputs.pow(2).sum().backward() + outputs_tp.pow(2).sum().backward() + + # Check that the input gradients are the same + with torch.no_grad(): + assert inputs.grad is not None + torch.testing.assert_close(inputs.grad, inputs_tp.grad) + + # And finally check that the parameter gradients are the same: + # Give the TP model the same weights as the non-TP model: + with torch.no_grad(): + mlp_tp.lin_0.weight.grad.data = mlp.lin_0.weight.grad.data.tensor_split(WORLD_SIZE, dim=0)[ + rank + ] + mlp_tp.lin_0.bias.grad.data = mlp.lin_0.bias.grad.data.tensor_split(WORLD_SIZE, dim=0)[rank] + mlp_tp.lin_1.weight.grad.data = mlp.lin_1.weight.grad.data.tensor_split(WORLD_SIZE, dim=1)[ + rank + ] + mlp_tp.lin_1.bias.grad.data = mlp.lin_1.bias.grad.data + + return f"Correct results on {rank=}" + + +def run(): + with ProcessPoolExecutor(max_workers=WORLD_SIZE) as pool: + ranks_list = [r for r in range(WORLD_SIZE)] + results = pool.map(test_mlp, ranks_list) + for r in results: + print(r) + + +if __name__ == "__main__": + run() diff --git a/blog/tp/tp_profiling.py b/blog/tp/tp_profiling.py new file mode 100644 index 0000000..6f8ec73 --- /dev/null +++ b/blog/tp/tp_profiling.py @@ -0,0 +1,163 @@ +import gc +import logging +import os + +import determined as det +import torch +import torch.distributed as dist + +import layers +import utils + +""" +Script for profiling the forward pass of TP MLP layers. Measures the iteration time and computes the +TFLOPs/sec/GPU for all availbable MLP configurations sharded across power-of-two GPUs (including +including the single GPU, non-TP case). + +Only intended for single-node use. +""" + + +def profile_and_report( + core_context: det.core.Context, + batch_size: int, + seq_len: int, + d_model: int, + num_repeats: int, + num_warmups: int, + device: torch.device, + rank: int, + tp_degree: int, + pg_dict: dict[int, dist.ProcessGroup], + dtype: torch.dtype = torch.bfloat16, +) -> None: + # This rank doesn't participate if it's not in the TP group. + if rank >= tp_degree: + return + + inputs = torch.randn(batch_size, seq_len, d_model, device=device, dtype=dtype) + if tp_degree == 1: + mlp = layers.MLP(d_model=d_model, dtype=dtype, device=device) + else: + mlp = layers.MLPTP(d_model=d_model, dtype=dtype, device=device, group=pg_dict[tp_degree]) + + # Use CUDA events for accurate timing. + timer = utils.CUDAEventTimer() + + # Warmups + for _ in range(num_warmups): + mlp(inputs) + + # Timed region. + for _ in range(num_repeats): + with timer: + mlp(inputs) + + # Mean and std TFLOP computations + mlp_flops = 16 * batch_size * seq_len * d_model**2 + + time_s_t = torch.tensor(timer.time_s_list, device=device) + # Use the worst-reported times across GPUs as the true timing metrics, if applicable. + if tp_degree > 1: + time_s_t = time_s_t.to(device) + dist.all_reduce(time_s_t, group=pg_dict[tp_degree], op=dist.ReduceOp.MAX) + time_s_t = time_s_t.cpu() + tflop_s_gpu_t = mlp_flops / time_s_t / 1e12 / tp_degree + metrics = { + "d_model": d_model, + "seq_len": seq_len, + "batch_size": batch_size, + "tp_degree": tp_degree, + "time_s": timer.time_s_mean, + "time_s_std": timer.time_s_std, + "tflop_s_gpu": tflop_s_gpu_t.mean().item(), + "tflop_s_gpu_std": tflop_s_gpu_t.std().item(), + } + + # report metrics on rank zero. Use d_model as the x-axis for plotting purposes. + if not rank: + core_context.train.report_metrics( + group=f"tp_degree_{tp_degree}", steps_completed=d_model, metrics=metrics + ) + + # Memory management + del mlp + del inputs + gc.collect() + torch.cuda.empty_cache() + + +def main( + core_context: det.core.Context, + batch_size: int, + seq_len: int, + d_model_min: int, + d_model_max: int, + d_model_step: int, + num_repeats: int, + num_warmups: int, +) -> None: + world_size = int(os.environ["WORLD_SIZE"]) + rank = int(os.environ["RANK"]) + device = torch.device(f"cuda:{rank}") + torch.cuda.set_device(device) + + # Profile every possible power-of-2 TP group size + def is_power_of_two(n: int) -> bool: + return n & (n - 1) == 0 + + tp_degrees = [n for n in range(1, world_size + 1) if is_power_of_two(n)] + # Create the non-trivial process groups + pg_dict = { + tp_degree: dist.new_group(list(range(tp_degree)), backend="nccl") + for tp_degree in tp_degrees + if tp_degree > 1 + } + + for tp_degree in tp_degrees: + for d_model in range(d_model_min, d_model_max + 1, d_model_step): + dist.barrier() + torch.cuda.synchronize() + profile_and_report( + core_context=core_context, + batch_size=batch_size, + seq_len=seq_len, + d_model=d_model, + num_repeats=num_repeats, + num_warmups=num_warmups, + rank=rank, + tp_degree=tp_degree, + pg_dict=pg_dict, + device=device, + ) + + +if __name__ == "__main__": + info = det.get_cluster_info() + assert info, "This script must run on a determined cluster." + hparams = info.trial.hparams + + # Set up determined's distributed code, if needed + try: + distributed = det.core.DistributedContext.from_torch_distributed() + dist.init_process_group("nccl") + except KeyError: + distributed = None + + try: + with det.core.init(distributed=distributed) as core_context: + logging.basicConfig(level=logging.INFO, format=det.LOG_FORMAT) + + main( + core_context=core_context, + batch_size=hparams["batch_size"], + seq_len=hparams["seq_len"], + d_model_min=hparams["d_model_min"], + d_model_max=hparams["d_model_max"], + d_model_step=hparams["d_model_step"], + num_repeats=hparams["num_repeats"], + num_warmups=hparams["num_warmups"], + ) + finally: + if distributed is not None: + dist.destroy_process_group() diff --git a/blog/tp/tp_profiling.yaml b/blog/tp/tp_profiling.yaml new file mode 100644 index 0000000..eb3c29a --- /dev/null +++ b/blog/tp/tp_profiling.yaml @@ -0,0 +1,22 @@ +name: MLP TP Profiling +# Adjust the workspace and project names, as appropriate. +workspace: TP Blog Post +project: MLP TP Profiling +resources: + slots_per_trial: 8 +searcher: + name: single + metric: not_used + max_length: 1 +hyperparameters: + batch_size: 1 + seq_len: 4096 + d_model_min: 1024 + d_model_max: 20480 + d_model_step: 512 + num_warmups: 5 + num_repeats: 100 +entrypoint: >- + python3 -m determined.launch.torch_distributed + python3 tp_profiling.py +max_restarts: 0 diff --git a/blog/tp/utils.py b/blog/tp/utils.py new file mode 100644 index 0000000..77e42d6 --- /dev/null +++ b/blog/tp/utils.py @@ -0,0 +1,68 @@ +import torch + + +class CUDAEventTimer: + """ + Helper class for timing CUDA operations. + + Example usage: + + ```python + # Time with `start` and `stop` methods: + + timer = CUDAEventTimer() + for iteration in range(repeats): + timer.start() + # Do some computation here + timer.stop() + time_list_s = timer.time_list_s # List of each iteration's duration in seconds + time_s_mean= timer.mean_time_s + + + # Or use as a context manager: + timer = CUDAEventTimer() + with timer: + # Do some computation here + elapsed_time_s = timer.total_time_s + ``` + """ + + def __init__(self) -> None: + self._start_events: list[torch.cuda.Event] = [] + self._end_events: list[torch.cuda.Event] = [] + + @property + def time_s_list(self) -> list[float]: + # https://discuss.pytorch.org/t/how-to-measure-time-in-pytorch/26964/11 + torch.cuda.synchronize() + time_list_s = [ + s.elapsed_time(e) / 1e3 for s, e in zip(self._start_events, self._end_events) + ] + return time_list_s + + @property + def time_s_total(self) -> float: + total_time_s = sum(self.time_s_list) + return total_time_s + + @property + def time_s_mean(self) -> float: + return self.time_s_total / len(self._start_events) + + @property + def time_s_std(self) -> float: + return torch.tensor(self.time_s_list).std().item() + + def start(self) -> None: + self._start_events.append(torch.cuda.Event(enable_timing=True)) + self._end_events.append(torch.cuda.Event(enable_timing=True)) + self._start_events[-1].record() + + def stop(self) -> None: + self._end_events[-1].record() + + def __enter__(self) -> None: + self.start() + + def __exit__(self, *args, **kwargs) -> None: + self.stop()