diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..97ef2fae --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,9 @@ +version: 2 + +build: + os: "ubuntu-20.04" + tools: + python: "mambaforge-4.10" + +conda: + environment: conda/environments/deployment_docs.yml diff --git a/extensions/rapids_version_templating.py b/extensions/rapids_version_templating.py index 96973dd6..92259d19 100644 --- a/extensions/rapids_version_templating.py +++ b/extensions/rapids_version_templating.py @@ -1,4 +1,24 @@ -def version_template(app, docname, source): +import re + +from docutils import nodes + + +class TextNodeVisitor(nodes.SparseNodeVisitor): + def __init__(self, app, *args, **kwargs): + self.app = app + super().__init__(*args, **kwargs) + + def visit_Text(self, node): + new_node = nodes.Text(re.sub(r"\{\{.*?\}\}", self.template_func, node.astext())) + node.parent.replace(node, new_node) + + def template_func(self, match): + return self.app.builder.templates.render_string( + match.group(), self.app.config.rapids_version + ) + + +def version_template(app, doctree, docname): """Substitute versions into each page. This allows documentation pages and notebooks to substiture in values like @@ -12,17 +32,12 @@ def version_template(app, docname, source): """ - # Make sure we're outputting HTML - if app.builder.format != "html": - return - src = source[0] - rendered = app.builder.templates.render_string(src, app.config.rapids_version) - source[0] = rendered + doctree.walk(TextNodeVisitor(app, doctree)) def setup(app): app.add_config_value("rapids_version", {}, "html") - app.connect("source-read", version_template) + app.connect("doctree-resolved", version_template) return { "version": "0.1", diff --git a/source/_static/images/examples/rapids-autoscaling-multi-tenant-kubernetes/jupyter-lab-dashboard.png b/source/_static/images/examples/rapids-autoscaling-multi-tenant-kubernetes/jupyter-lab-dashboard.png new file mode 100644 index 00000000..97922522 Binary files /dev/null and b/source/_static/images/examples/rapids-autoscaling-multi-tenant-kubernetes/jupyter-lab-dashboard.png differ diff --git a/source/cloud/aws/sagemaker.md b/source/cloud/aws/sagemaker.md index f4ecb603..3407db4b 100644 --- a/source/cloud/aws/sagemaker.md +++ b/source/cloud/aws/sagemaker.md @@ -35,9 +35,9 @@ mamba create -y -n rapids {{ rapids_conda_channels }} {{ rapids_conda_packages } conda activate rapids # optionally install AutoGluon for AutoML GPU demo -# anaconda3/envs/rapids/bin/python -m pip install --pre autogluon +# python -m pip install --pre autogluon -anaconda3/envs/rapids/bin/python -m ipykernel install --user --name rapids +python -m ipykernel install --user --name rapids echo "kernel install completed" EOF ``` @@ -68,7 +68,7 @@ All you’ll need to do is bring in your RAPIDS training script and libraries as ![Screenshot of summarized step to build Estimator](../../images/sagemaker-containerize-and-publish.png) -- Having built our container [ +custom logic], compile all efforts into an Estimator instance. Test the Estimator and run parallel hyperparameter optimization tuning jobs. +- Having built our container and custom logic, we can now assemble all components into an Estimator. We can now test the Estimator and run parallel hyperparameter optimization tuning jobs. ```python estimator = sagemaker.estimator.Estimator( diff --git a/source/cloud/azure/azure-vm-multi.md b/source/cloud/azure/azure-vm-multi.md index cb8942b9..11584292 100644 --- a/source/cloud/azure/azure-vm-multi.md +++ b/source/cloud/azure/azure-vm-multi.md @@ -31,14 +31,14 @@ cluster = AzureVMCluster( resource_group=resource_group, vnet=vnet, security_group=security_group, - subscription_id=security_group, + subscription_id=subscription_id, location="westus2", vm_size="Standard_NC12s_v3", public_ingress=True, disk_size=100, n_workers=2, worker_class="dask_cuda.CUDAWorker", - docker_image={{rapids_container}}, + docker_image="{{rapids_container}}", docker_args="-e DISABLE_JUPYTER=true -p 8787:8787 -p 8786:8786", ) ``` diff --git a/source/cloud/gcp/dataproc.md b/source/cloud/gcp/dataproc.md index f171b76f..bfe9c571 100644 --- a/source/cloud/gcp/dataproc.md +++ b/source/cloud/gcp/dataproc.md @@ -10,10 +10,9 @@ It is strongly recommended that you copy the initialization scripts into your ow $ REGION= $ GCS_BUCKET= $ gcloud storage buckets create gs://$GCS_BUCKET -$ gsutil cp gs://goog-dataproc-initialization-actions-${REGION}/gpu/install_gpu_driver.sh,\ - gs://goog-dataproc-initialization-actions-${REGION}/dask/dask.sh,\ - gs://goog-dataproc-initialization-actions-${REGION}/rapids/rapids.sh\ - gs://$GCS_BUCKET +$ gsutil cp gs://goog-dataproc-initialization-actions-${REGION}/gpu/install_gpu_driver.sh gs://$GCS_BUCKET +$ gsutil cp gs://goog-dataproc-initialization-actions-${REGION}/dask/dask.sh gs://$GCS_BUCKET +$ gsutil cp gs://goog-dataproc-initialization-actions-${REGION}/rapids/rapids.sh gs://$GCS_BUCKET ``` @@ -29,7 +28,7 @@ $ gcloud dataproc clusters create $CLUSTER_NAME\ --master-accelerator type=nvidia-tesla-t4,count=2\ --worker-machine-type n1-standard-32\ --worker-accelerator type=nvidia-tesla-t4,count=2\ - --initialization-actions=$GCS_BUCKET/install_gpu_driver.sh,gs://$GCS_BUCKET/dask.sh,gs://$GCS_BUCKET/rapids.sh\ + --initialization-actions=gs://$GCS_BUCKET/install_gpu_driver.sh,gs://$GCS_BUCKET/dask.sh,gs://$GCS_BUCKET/rapids.sh\ --initialization-action-timeout 60m\ --optional-components=JUPYTER\ --metadata gpu-driver-provider=NVIDIA,dask-runtime=$DASK_RUNTIME,rapids-runtime=DASK\ diff --git a/source/conf.py b/source/conf.py index 81de48b9..2ed568f9 100644 --- a/source/conf.py +++ b/source/conf.py @@ -22,14 +22,14 @@ versions = { "stable": { - "rapids_container": "rapidsai/rapidsai-core:22.12-cuda11.5-runtime-ubuntu20.04-py3.9", + "rapids_container": "rapidsai/rapidsai-core:23.02-cuda11.5-runtime-ubuntu20.04-py3.10", "rapids_conda_channels": "-c rapidsai -c conda-forge -c nvidia", - "rapids_conda_packages": "rapids=22.12 python=3.9 cudatoolkit=11.5", + "rapids_conda_packages": "rapids=23.02 python=3.10 cudatoolkit=11.5", }, "nightly": { - "rapids_container": "rapidsai/rapidsai-core-nightly:23.02-cuda11.5-runtime-ubuntu20.04-py3.9", + "rapids_container": "rapidsai/rapidsai-core-nightly:23.04-cuda11.5-runtime-ubuntu20.04-py3.10", "rapids_conda_channels": "-c rapidsai-nightly -c conda-forge -c nvidia", - "rapids_conda_packages": "rapids=23.02 python=3.9 cudatoolkit=11.5", + "rapids_conda_packages": "rapids=23.04 python=3.10 cudatoolkit=11.5", }, } rapids_version = ( @@ -67,6 +67,9 @@ # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] +copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " +copybutton_prompt_is_regexp = True + # -- Options for notebooks ------------------------------------------------- nb_execution_mode = "off" diff --git a/source/examples/index.md b/source/examples/index.md index 83527a4d..27c6532c 100644 --- a/source/examples/index.md +++ b/source/examples/index.md @@ -10,4 +10,5 @@ rapids-optuna-hpo/notebook rapids-sagemaker-higgs/notebook rapids-sagemaker-hpo/notebook rapids-ec2-mnmg/notebook +rapids-autoscaling-multi-tenant-kubernetes/notebook ``` diff --git a/source/examples/rapids-autoscaling-multi-tenant-kubernetes/image-prepuller.yaml b/source/examples/rapids-autoscaling-multi-tenant-kubernetes/image-prepuller.yaml new file mode 100644 index 00000000..93fae8d0 --- /dev/null +++ b/source/examples/rapids-autoscaling-multi-tenant-kubernetes/image-prepuller.yaml @@ -0,0 +1,21 @@ +# image-prepuller.yaml +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: prepull-rapids +spec: + selector: + matchLabels: + name: prepull-rapids + template: + metadata: + labels: + name: prepull-rapids + spec: + initContainers: + - name: prepull-rapids + image: us-central1-docker.pkg.dev/nv-ai-infra/rapidsai/rapidsai-core:22.12-cuda11.5-runtime-ubuntu20.04-py3.9 + command: ["sh", "-c", "'true'"] + containers: + - name: pause + image: gcr.io/google_containers/pause diff --git a/source/examples/rapids-autoscaling-multi-tenant-kubernetes/notebook.ipynb b/source/examples/rapids-autoscaling-multi-tenant-kubernetes/notebook.ipynb new file mode 100644 index 00000000..6823643d --- /dev/null +++ b/source/examples/rapids-autoscaling-multi-tenant-kubernetes/notebook.ipynb @@ -0,0 +1,2268 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Autoscaling multi-tenant Kubernetes Deep-Dive\n", + "\n", + "In this example we are going to take a deep-dive into launching an autoscaling multi-tenant RAPIDS environment on Kubernetes.\n", + "\n", + "Being able to scale out your workloads and only pay for the resources you use is a fantastic way to save costs when using RAPIDS. If you have many folks in your organization who all want to be able to do this you can get added benefits by pooling your resources into an autoscaling Kubernetes cluster.\n", + "\n", + "Let's run through the steps required to launch a Kubernetes cluster on [Google Cloud](https://cloud.google.com), then simulate the workloads of many users sharing the cluster. Then we can explore what that experience was like both from a user perspective and also from a cost perspective." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Prerequisites\n", + "\n", + "Before we get started you'll need to ensure you have a few CLI tools installed.\n", + "\n", + "- [`gcloud`](https://cloud.google.com/sdk/gcloud) (and make sure you run [`gcloud auth login`](https://cloud.google.com/sdk/gcloud/reference/auth/login))\n", + "- [`kubectl`](https://kubernetes.io/docs/tasks/tools/)\n", + "- [`helm`](https://helm.sh/docs/intro/install/)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Get a Kubernetes Cluster\n", + "\n", + "For this example we are going to use [Google Cloud's Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) to launch a cluster.\n", + "\n", + "````{docref} /cloud/gcp/gke\n", + "We are going to follow the RAPIDS GKE deployment instructions but we will modify our cluster creation command to enable Kubernetes cluster autoscaling out of the box.\n", + "\n", + "```\n", + "--enable-autoscaling --autoscaling-profile optimize-utilization \\\n", + "--num-nodes 1 --min-nodes 1 --max-nodes 20\n", + "```\n", + "\n", + "Data science container images are also notiriously large so we will enable image streaming to speed up our container creation.\n", + "\n", + "```\n", + "--image-type=\"COS_CONTAINERD\" --enable-image-streaming\n", + "```\n", + "````" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Default change: VPC-native is the default mode during cluster creation for versions greater than 1.21.0-gke.1500. To create advanced routes based clusters, please pass the `--no-enable-ip-alias` flag\n", + "Default change: During creation of nodepools or autoscaling configuration changes for cluster versions greater than 1.24.1-gke.800 a default location policy is applied. For Spot and PVM it defaults to ANY, and for all other VM kinds a BALANCED policy is used. To change the default values use the `--location-policy` flag.\n", + "Note: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s).\n", + "Note: Machines with GPUs have certain limitations which may affect your workflow. Learn more at https://cloud.google.com/kubernetes-engine/docs/how-to/gpus\n", + "Creating cluster multi-tenant-rapids in us-central1... Cluster is being configu\n", + "red...⠼ \n", + "Creating cluster multi-tenant-rapids in us-central1... Cluster is being deploye\n", + "d...⠏ \n", + "Creating cluster multi-tenant-rapids in us-central1... Cluster is being health-\n", + "checked (master is healthy)...done. \n", + "Created [https://container.googleapis.com/v1/projects/nv-ai-infra/zones/us-central1/clusters/multi-tenant-rapids].\n", + "To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1/multi-tenant-rapids?project=nv-ai-infra\n", + "kubeconfig entry generated for multi-tenant-rapids.\n", + "NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS\n", + "multi-tenant-rapids us-central1 1.23.14-gke.1800 104.197.37.225 n1-standard-4 1.23.14-gke.1800 2 RUNNING\n" + ] + } + ], + "source": [ + "! gcloud container clusters create multi-tenant-rapids \\\n", + " --accelerator type=nvidia-tesla-t4,count=2 --machine-type n1-standard-4 \\\n", + " --region us-central1 --node-locations us-central1-b,us-central1-c \\\n", + " --release-channel stable \\\n", + " --enable-autoscaling --autoscaling-profile optimize-utilization \\\n", + " --num-nodes 1 --min-nodes 1 --max-nodes 20 \\\n", + " --image-type=\"COS_CONTAINERD\" --enable-image-streaming" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have our cluster let's [install the NVIDIA Drivers](https://cloud.google.com/kubernetes-engine/docs/how-to/gpus#installing_drivers)." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "daemonset.apps/nvidia-driver-installer created\n" + ] + } + ], + "source": [ + "! kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/cos/daemonset-preloaded-latest.yaml" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Observability\n", + "\n", + "Once we have run some workloads on our Kubernetes cluster we will want to be able to go back through the cluster telemetry data to see how our autoscaling behaved. To do this let's install [Prometheus](https://prometheus.io/) so that we are recording cluster metrics and can explore them later." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Prometheus stack\n", + "\n", + "Let's start by installing the [Kubernetes Prometheus Stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) which includes everything we need to run Prometheus on our cluster.\n", + "\n", + "We need to add a couple of extra configuration options to ensure Prometheus is collecting data frequently enough to analyse, which you will find in `prometheus-stack-values.yaml`." + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# prometheus-stack-values.yaml\n", + "serviceMonitorSelectorNilUsesHelmValues: false\n", + "\n", + "prometheus:\n", + " prometheusSpec:\n", + " # Setting this to a high frequency so that we have richer data for analysis later\n", + " scrapeInterval: 1s\n" + ] + } + ], + "source": [ + "! cat prometheus-stack-values.yaml" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME: kube-prometheus-stack\n", + "LAST DEPLOYED: Tue Feb 21 09:19:39 2023\n", + "NAMESPACE: prometheus\n", + "STATUS: deployed\n", + "REVISION: 1\n", + "NOTES:\n", + "kube-prometheus-stack has been installed. Check its status by running:\n", + " kubectl --namespace prometheus get pods -l \"release=kube-prometheus-stack\"\n", + "\n", + "Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator.\n" + ] + } + ], + "source": [ + "! helm install --repo https://prometheus-community.github.io/helm-charts kube-prometheus-stack kube-prometheus-stack \\\n", + " --create-namespace --namespace prometheus \\\n", + " --values prometheus-stack-values.yaml" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have Prometheus running and collecting data we can move on and install RAPIDS and run some workloads. We will come back to these tools later when we want to explore the data we have collected." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Install RAPIDS\n", + "\n", + "For this RAPIDS installation we are going to use a single [Jupyter Notebook Pod](/platforms/kubernetes) and the [Dask Operator](/tools/kubernetes/dask-operator). In a real deployment you would use something like [JupyterHub](https://jupyter.org/hub) or [Kubeflow Notebooks](https://www.kubeflow.org/docs/components/notebooks/) to create a notebook spawning service with user authentication, but that is out of scope for this example.\n", + "\n", + "```{docref} /platforms/kubernetes\n", + "There are many ways to install RAPIDS on Kubernetes. You can find detailed instructions on all of the various methods in the documentation.\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Image steaming (optional)\n", + "\n", + "In order to steam the container image to the GKE nodes our image needs to be stored in [Google Cloud Artifact Registry](https://cloud.google.com/artifact-registry/) in the same region as our cluster.\n", + "\n", + "```console\n", + "$ docker pull rapidsai/rapidsai-core:22.12-cuda11.5-runtime-ubuntu20.04-py3.9\n", + "\n", + "$ docker tag rapidsai/rapidsai-core:22.12-cuda11.5-runtime-ubuntu20.04-py3.9 REGION-docker.pkg.dev/PROJECT/REPO/IMAGE:TAG\n", + "\n", + "$ docker push REGION-docker.pkg.dev/PROJECT/REPO/IMAGE:TAG\n", + "```\n", + "\n", + "Be sure to replace the image throughout the notebook with the one that you have pushed to your own Google Cloud project." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Image prepuller (optional)\n", + "\n", + "If you know that many users are going to want to frequently pull a specific container image I like to run a small `DaemonSet` which ensures that image starts streaming onto a node as soon as it joins the cluster. This is optional but can reduce wait time for users." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# image-prepuller.yaml\n", + "apiVersion: apps/v1\n", + "kind: DaemonSet\n", + "metadata:\n", + " name: prepull-rapids\n", + "spec:\n", + " selector:\n", + " matchLabels:\n", + " name: prepull-rapids\n", + " template:\n", + " metadata:\n", + " labels:\n", + " name: prepull-rapids\n", + " spec:\n", + " initContainers:\n", + " - name: prepull-rapids\n", + " image: rapidsai/rapidsai-core:22.12-cuda11.5-runtime-ubuntu20.04-py3.9\n", + " command: [\"sh\", \"-c\", \"'true'\"]\n", + " containers:\n", + " - name: pause\n", + " image: gcr.io/google_containers/pause\n" + ] + } + ], + "source": [ + "! cat image-prepuller.yaml" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "daemonset.apps/prepull-rapids created\n" + ] + } + ], + "source": [ + "! kubectl apply -f image-prepuller.yaml" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### RAPIDS Notebook Pod\n", + "\n", + "Now let's launch a Notebook Pod. \n", + "\n", + "````{note}\n", + "From this Pod we are going to want to be able to spawn Dask cluster resources on Kubernetes, so we need to ensure the Pod has the appropriate permissions to interact with the Kubernetes API. \n", + "\n", + "```{docref} /platforms/kubernetes\n", + "Check out the extended notebook contiguration documentation for more details.\n", + "```\n", + "````" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "serviceaccount/rapids-dask created\n", + "role.rbac.authorization.k8s.io/rapids-dask created\n", + "rolebinding.rbac.authorization.k8s.io/rapids-dask created\n", + "configmap/jupyter-server-proxy-config created\n", + "service/rapids-notebook created\n", + "pod/rapids-notebook created\n" + ] + } + ], + "source": [ + "! kubectl apply -f rapids-notebook.yaml" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Install the Dask Operator\n", + "\n", + "Lastly we need to install the Dask Operator so we can spawn RAPIDS Dask cluster from our Notebook session.\n", + "\n", + "```{docref} /tools/kubernetes/dask-operator\n", + "See the RAPIDS Dask Operator documentation for more information.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME: dask-kubernetes-operator-1676971371\n", + "LAST DEPLOYED: Tue Feb 21 09:23:06 2023\n", + "NAMESPACE: dask-operator\n", + "STATUS: deployed\n", + "REVISION: 1\n", + "TEST SUITE: None\n", + "NOTES:\n", + "Operator has been installed successfully.\n" + ] + } + ], + "source": [ + "! helm install --repo https://helm.dask.org dask-kubernetes-operator \\\n", + " --generate-name --create-namespace --namespace dask-operator " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Running some work\n", + "\n", + "Next let's connect to the Jupyter session and run some work on our cluster. You can do this by port forwarding the Jupyter service to your local machine.\n", + "\n", + "```console\n", + "$ kubectl port-forward svc/rapids-notebook 8888:8888 \n", + "Forwarding from 127.0.0.1:8888 -> 8888\n", + "Forwarding from [::1]:8888 -> 8888\n", + "```\n", + "\n", + "Then open http://localhost:8888 in your browser.\n", + "\n", + "```{note}\n", + "If you are following along with this notebook locally you will also want to upload it to the Jupyter session and continue running the cells from there.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Check our capabilities\n", + "\n", + "Let's make sure our environment is all set up correctly by checking out our capabilities. We can start by running `nvidia-smi` to inspect our Notebook GPU." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tue Feb 21 14:50:01 2023 \n", + "+-----------------------------------------------------------------------------+\n", + "| NVIDIA-SMI 510.47.03 Driver Version: 510.47.03 CUDA Version: 11.6 |\n", + "|-------------------------------+----------------------+----------------------+\n", + "| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |\n", + "| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |\n", + "| | | MIG M. |\n", + "|===============================+======================+======================|\n", + "| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |\n", + "| N/A 41C P8 14W / 70W | 0MiB / 15360MiB | 0% Default |\n", + "| | | N/A |\n", + "+-------------------------------+----------------------+----------------------+\n", + " \n", + "+-----------------------------------------------------------------------------+\n", + "| Processes: |\n", + "| GPU GI CI PID Type Process name GPU Memory |\n", + "| ID ID Usage |\n", + "|=============================================================================|\n", + "| No running processes found |\n", + "+-----------------------------------------------------------------------------+\n" + ] + } + ], + "source": [ + "! nvidia-smi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Great we can see our notebook has an NVIDIA T4. Now let's use `kubectl` to inspect our cluster. We won't actually have `kubectl` installed in our remote Jupyter environment so let's do that first." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Preparing transaction: ...working... done\n", + "Verifying transaction: ...working... done\n", + "Executing transaction: ...working... done\n" + ] + } + ], + "source": [ + "! mamba install --quiet -c conda-forge kubernetes-client -y" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME READY STATUS RESTARTS AGE\n", + "prepull-rapids-l5qgt 1/1 Running 0 3m24s\n", + "prepull-rapids-w8xcj 1/1 Running 0 3m24s\n", + "rapids-notebook 1/1 Running 0 2m54s\n" + ] + } + ], + "source": [ + "! kubectl get pods" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can see our prepull Pods we created earlier alongside our `rapids-notebook` Pod that we are currently in. As we created the prepull Pod via a `DaemonSet` we also know that there are two nodes in our Kubernetes cluster because there are two prepull Pods. As our cluster scales we will see more of them appear." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No resources found in default namespace.\n" + ] + } + ], + "source": [ + "! kubectl get daskclusters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also see that we currently have no `DaskCluster` resources, but this is good because we didn't get a `server doesn't have a resource type \"daskclusters\"` error so we know the Dask Operator also installed successfully." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Small workload\n", + "\n", + "Let's run a small RAPIDS workload that stretches our Kubernetes cluster a little and causes it to scale. \n", + "\n", + "We know that we have two nodes in our Kubernetes cluster and we selected a node type with 2 GPUs when we launched it on GKE. Our Notebook Pod is taking up one GPU so we have three remaining. If we launch a Dask Cluster we will need one GPU for the scheduler and one for each worker. So let's create a Dask cluster with four workers which will cause our Kubernetes to add one more node." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First let's install `dask-kubernetes` so we can create our `DaskCluster` resources from Python. We will also install `gcsfs` so that our workload can read data from [Google Cloud Storage](https://cloud.google.com/storage)." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Preparing transaction: ...working... done\n", + "Verifying transaction: ...working... done\n", + "Executing transaction: ...working... done\n" + ] + } + ], + "source": [ + "! mamba install --quiet -c conda-forge dask-kubernetes gcsfs -y" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Unclosed client session\n", + "client_session: \n", + "Unclosed connection\n", + "client_connection: Connection\n" + ] + } + ], + "source": [ + "from dask_kubernetes.operator import KubeCluster\n", + "\n", + "cluster = KubeCluster(\n", + " name=\"rapids-dask-1\",\n", + " image=\"rapidsai/rapidsai-core:22.12-cuda11.5-runtime-ubuntu20.04-py3.9\", # Replace me with your cached image\n", + " n_workers=4,\n", + " resources={\"limits\": {\"nvidia.com/gpu\": \"1\"}},\n", + " env={\"DISABLE_JUPYTER\": \"true\", \"EXTRA_PIP_PACKAGES\": \"gcsfs\"},\n", + " worker_command=\"dask-cuda-worker\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Great our Dask cluster was created but right now we just have a scheduler with half of our workers. We can use `kubectl` to see what is happening." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME READY STATUS RESTARTS AGE\n", + "prepull-rapids-l5qgt 1/1 Running 0 6m18s\n", + "prepull-rapids-w8xcj 1/1 Running 0 6m18s\n", + "rapids-dask-1-default-worker-5f59bc8e7a 0/1 Pending 0 68s\n", + "rapids-dask-1-default-worker-88ab088b7c 0/1 Pending 0 68s\n", + "rapids-dask-1-default-worker-b700343afe 1/1 Running 0 68s\n", + "rapids-dask-1-default-worker-e0bb7fff2d 1/1 Running 0 68s\n", + "rapids-dask-1-scheduler 1/1 Running 0 69s\n", + "rapids-notebook 1/1 Running 0 5m48s\n" + ] + } + ], + "source": [ + "! kubectl get pods" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We see here that most of our Pods are `Running` but two workers are `Pending`. This is because we don't have enough GPUs for them right now. We can look at the events on our pending pods for more information." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LAST SEEN TYPE REASON OBJECT MESSAGE\n", + "50s Warning FailedScheduling pod/rapids-dask-1-default-worker-5f59bc8e7a 0/2 nodes are available: 2 Insufficient nvidia.com/gpu.\n", + "12s Normal TriggeredScaleUp pod/rapids-dask-1-default-worker-5f59bc8e7a pod triggered scale-up: [{https://www.googleapis.com/compute/v1/projects/nv-ai-infra/zones/us-central1-b/instanceGroups/gke-multi-tenant-rapids-default-pool-3a6a793f-grp 1->2 (max: 20)}]\n" + ] + } + ], + "source": [ + "! kubectl get event --field-selector involvedObject.name=rapids-dask-1-default-worker-5f59bc8e7a" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we can see that our Pod triggered the cluster to scale from one to two nodes. If we wait for our new node to come online we should see a few things happen. \n", + "\n", + "- First there will be a new prepull Pod scheduled on the new node which will start streaming the RAPIDS container image.\n", + "- Other Pods in the `kube-system` namespace will be scheduled to install NVIDIA drivers and update the Kubernetes API.\n", + "- Then once the GPU drivers have finished installing the worker Pods will be scheduled onto our new node\n", + "- Then once the image is ready our Pods move into a `Running` phase." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME READY STATUS RESTARTS AGE\n", + "prepull-rapids-l5qgt 1/1 Running 0 6m41s\n", + "prepull-rapids-w8xcj 1/1 Running 0 6m41s\n", + "rapids-dask-1-default-worker-5f59bc8e7a 0/1 Pending 0 91s\n", + "rapids-dask-1-default-worker-88ab088b7c 0/1 Pending 0 91s\n", + "rapids-dask-1-default-worker-b700343afe 1/1 Running 0 91s\n", + "rapids-dask-1-default-worker-e0bb7fff2d 1/1 Running 0 91s\n", + "rapids-dask-1-scheduler 1/1 Running 0 92s\n", + "rapids-notebook 1/1 Running 0 6m11s\n", + "prepull-rapids-69pbq 0/1 Pending 0 0s\n", + "prepull-rapids-69pbq 0/1 Pending 0 0s\n", + "prepull-rapids-69pbq 0/1 Init:0/1 0 4s\n", + "rapids-dask-1-default-worker-88ab088b7c 0/1 Pending 0 2m3s\n", + "prepull-rapids-69pbq 0/1 Init:0/1 0 9s\n", + "prepull-rapids-69pbq 0/1 PodInitializing 0 15s\n", + "rapids-dask-1-default-worker-5f59bc8e7a 0/1 Pending 0 2m33s\n", + "prepull-rapids-69pbq 1/1 Running 0 3m7s\n", + "rapids-dask-1-default-worker-5f59bc8e7a 0/1 Pending 0 5m13s\n", + "rapids-dask-1-default-worker-88ab088b7c 0/1 Pending 0 5m13s\n", + "rapids-dask-1-default-worker-5f59bc8e7a 0/1 ContainerCreating 0 5m14s\n", + "rapids-dask-1-default-worker-88ab088b7c 0/1 ContainerCreating 0 5m14s\n", + "rapids-dask-1-default-worker-5f59bc8e7a 1/1 Running 0 5m26s\n", + "rapids-dask-1-default-worker-88ab088b7c 1/1 Running 0 5m26s\n", + "^C\n" + ] + } + ], + "source": [ + "! kubectl get pods -w" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Awesome we can now run some work on our Dask cluster." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + "
\n", + "

Client

\n", + "

Client-3722820c-b1f8-11ed-8042-fa6ca111b70e

\n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
Connection method: Cluster objectCluster type: dask_kubernetes.KubeCluster
\n", + " Dashboard: /proxy/rapids-dask-1-scheduler.default:8787/status\n", + "
\n", + "\n", + " \n", + " \n", + " \n", + "\n", + " \n", + "
\n", + "

Cluster Info

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

KubeCluster

\n", + "

rapids-dask-1

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Dashboard: /proxy/rapids-dask-1-scheduler.default:8787/status\n", + " \n", + " Workers: 2\n", + "
\n", + " Total threads: 2\n", + " \n", + " Total memory: 29.30 GiB\n", + "
\n", + "\n", + "
\n", + " \n", + "

Scheduler Info

\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

Scheduler

\n", + "

Scheduler-5ef1a738-4ae1-4f07-ab68-160cfda35431

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Comm: tcp://10.28.1.6:8786\n", + " \n", + " Workers: 2\n", + "
\n", + " Dashboard: /proxy/10.28.1.6:8787/status\n", + " \n", + " Total threads: 2\n", + "
\n", + " Started: 5 minutes ago\n", + " \n", + " Total memory: 29.30 GiB\n", + "
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "

Workers

\n", + "
\n", + "\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: rapids-dask-1-default-worker-b700343afe

\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", + " Comm: tcp://10.28.0.24:35501\n", + " \n", + " Total threads: 1\n", + "
\n", + " Dashboard: /proxy/10.28.0.24:44477/status\n", + " \n", + " Memory: 14.65 GiB\n", + "
\n", + " Nanny: tcp://10.28.0.24:41347\n", + "
\n", + " Local directory: /tmp/dask-worker-space/worker-x_t6bef5\n", + "
\n", + " GPU: Tesla T4\n", + " \n", + " GPU memory: 15.00 GiB\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: rapids-dask-1-default-worker-e0bb7fff2d

\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", + " Comm: tcp://10.28.0.23:46035\n", + " \n", + " Total threads: 1\n", + "
\n", + " Dashboard: /proxy/10.28.0.23:42637/status\n", + " \n", + " Memory: 14.65 GiB\n", + "
\n", + " Nanny: tcp://10.28.0.23:38783\n", + "
\n", + " Local directory: /tmp/dask-worker-space/worker-8z3017h5\n", + "
\n", + " GPU: Tesla T4\n", + " \n", + " GPU memory: 15.00 GiB\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "\n", + "
\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "\n", + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from dask.distributed import Client, wait\n", + "\n", + "client = Client(cluster)\n", + "client" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's load some data from GCS into memory on our GPUs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "import dask.config\n", + "import dask.dataframe as dd\n", + "\n", + "dask.config.set({\"dataframe.backend\": \"cudf\"})\n", + "\n", + "df = dd.read_parquet(\n", + " \"gcs://anaconda-public-data/nyc-taxi/2015.parquet\",\n", + " storage_options={\"token\": \"cloud\"},\n", + ").persist()\n", + "wait(df)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can do some calculation. This can be whatever you want to do with your data, for this example let's do something quick like calculating the haversine distance between the pickup and dropoff locations (yes calculating this on ~100M rows is a quick task for RAPIDS 😁)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from cuspatial import haversine_distance\n", + "\n", + "\n", + "def map_haversine(part):\n", + " return haversine_distance(\n", + " part[\"pickup_longitude\"],\n", + " part[\"pickup_latitude\"],\n", + " part[\"dropoff_longitude\"],\n", + " part[\"dropoff_latitude\"],\n", + " )\n", + "\n", + "\n", + "df[\"haversine_distance\"] = df.map_partitions(map_haversine)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.44 s, sys: 853 ms, total: 2.29 s\n", + "Wall time: 4.66 s\n" + ] + }, + { + "data": { + "text/plain": [ + "tpep_pickup_datetime\n", + "2015-01-01 00:00:00 4.326464\n", + "2015-01-01 00:00:00 8666.633292\n", + "2015-01-01 00:00:00 1.285498\n", + "2015-01-01 00:00:01 0.827326\n", + "2015-01-01 00:00:03 2.267110\n", + " ... \n", + "2015-12-31 23:59:56 1.570824\n", + "2015-12-31 23:59:58 2.340270\n", + "2015-12-31 23:59:59 2.801575\n", + "2015-12-31 23:59:59 5.091840\n", + "2015-12-31 23:59:59 0.927577\n", + "Name: haversine_distance, Length: 146112989, dtype: float64" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "df[\"haversine_distance\"].compute()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Great, so we now have a little toy workloads that opens some data, does some calculation and takes a bit of time.\n", + "\n", + "Let's remove our single Dask cluster and switch to simulating many workloads running at once." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "client.close()\n", + "cluster.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simulating many multi-tenant workloads\n", + "\n", + "Now we have a toy workload which we can use to represent one user on our multi-tenant cluster.\n", + "\n", + "Let's now construct a larger graph to simulate lots of users spinning up Dask clusters and running workloads." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First let's create a function that contains our whole workload including our cluster setup." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "import dask.delayed\n", + "\n", + "\n", + "@dask.delayed\n", + "def run_haversine(*args):\n", + " from dask_kubernetes.operator import KubeCluster\n", + " from dask.distributed import Client, wait\n", + " import uuid\n", + " import dask.config\n", + " import dask.dataframe as dd\n", + "\n", + " dask.config.set({\"dataframe.backend\": \"cudf\"})\n", + "\n", + " def map_haversine(part):\n", + " from cuspatial import haversine_distance\n", + "\n", + " return haversine_distance(\n", + " part[\"pickup_longitude\"],\n", + " part[\"pickup_latitude\"],\n", + " part[\"dropoff_longitude\"],\n", + " part[\"dropoff_latitude\"],\n", + " )\n", + "\n", + " with KubeCluster(\n", + " name=\"rapids-dask-\" + uuid.uuid4().hex[:5],\n", + " image=\"rapidsai/rapidsai-core:22.12-cuda11.5-runtime-ubuntu20.04-py3.9\", # Replace me with your cached image\n", + " n_workers=2,\n", + " resources={\"limits\": {\"nvidia.com/gpu\": \"1\"}},\n", + " env={\"DISABLE_JUPYTER\": \"true\", \"EXTRA_PIP_PACKAGES\": \"gcsfs\"},\n", + " worker_command=\"dask-cuda-worker\",\n", + " resource_timeout=600,\n", + " ) as cluster:\n", + " with Client(cluster) as client:\n", + " client.wait_for_workers(2)\n", + " df = dd.read_parquet(\n", + " \"gcs://anaconda-public-data/nyc-taxi/2015.parquet\",\n", + " storage_options={\"token\": \"cloud\"},\n", + " )\n", + " client.compute(df.map_partitions(map_haversine))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now if we run this function we will launch a Dask cluster and run our workload. We will use context managers to ensure our Dask cluster gets cleaned up when the work is complete. Given that we have no active Dask clusters this function will be executed on the Notebook Pod." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Unclosed client session\n", + "client_session: \n", + "Unclosed connection\n", + "client_connection: Connection\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 194 ms, sys: 30 ms, total: 224 ms\n", + "Wall time: 23.6 s\n" + ] + } + ], + "source": [ + "%%time\n", + "run_haversine().compute()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Great that works, so we have a self contained RAPIDS workload that launches its own Dask cluster and performs some work." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulating our multi-tenant workloads\n", + "\n", + "To see how our Kubernetes cluster behaves when many users are sharing it we want to run our haversine workload a bunch of times. \n", + "\n", + "```{note}\n", + "If you're not interested in how we simulate this workload feel free to skip onto the analysis section.\n", + "```\n", + "\n", + "To do this we can create another Dask cluster which we will use to pilot our workloads. This cluster will be a proxy for the Jupyter sessions our users would be interacting with. Then we will construct a Dask graph which runs our haversine workload many times in various configurations to simulate different users submitting different workloads on an ad-hoc basis." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Unclosed client session\n", + "client_session: \n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ebd78135bcbd4e449eaa0736556e8e60", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "
\n", + "
\n", + "
\n", + "
\n", + "

KubeCluster

\n", + "

mock-jupyter-cluster

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Dashboard: /proxy/mock-jupyter-cluster-scheduler.default:8787/status\n", + " \n", + " Workers: 0\n", + "
\n", + " Total threads: 0\n", + " \n", + " Total memory: 0 B\n", + "
\n", + "\n", + "
\n", + " \n", + "

Scheduler Info

\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

Scheduler

\n", + "

Scheduler-f6d55e0c-a7b1-4dfd-80b4-be0566b14cce

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Comm: tcp://10.28.1.12:8786\n", + " \n", + " Workers: 0\n", + "
\n", + " Dashboard: /proxy/10.28.1.12:8787/status\n", + " \n", + " Total threads: 0\n", + "
\n", + " Started: Just now\n", + " \n", + " Total memory: 0 B\n", + "
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "

Workers

\n", + "
\n", + "\n", + " \n", + "\n", + "
\n", + "
\n", + "\n", + "
\n", + "
\n", + "
" + ], + "text/plain": [ + "KubeCluster(mock-jupyter-cluster, 'tcp://mock-jupyter-cluster-scheduler.default:8786', workers=0, threads=0, memory=0 B)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from dask_kubernetes.operator import KubeCluster, make_cluster_spec\n", + "\n", + "cluster_spec = make_cluster_spec(\n", + " name=\"mock-jupyter-cluster\",\n", + " image=\"rapidsai/rapidsai-core:22.12-cuda11.5-runtime-ubuntu20.04-py3.9\", # Replace me with your cached image\n", + " n_workers=1,\n", + " resources={\"limits\": {\"nvidia.com/gpu\": \"1\"}, \"requests\": {\"cpu\": \"50m\"}},\n", + " env={\"DISABLE_JUPYTER\": \"true\", \"EXTRA_PIP_PACKAGES\": \"gcsfs dask-kubernetes\"},\n", + ")\n", + "cluster_spec[\"spec\"][\"worker\"][\"spec\"][\"serviceAccountName\"] = \"rapids-dask\"\n", + "\n", + "cluster = KubeCluster(custom_cluster_spec=cluster_spec)\n", + "cluster" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We need to ensure our workers have the same dependencies as our Notebook session here so that it can spawn more Dask clusters so we install `gcsfs` and `dask-kubernetes`." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + "
\n", + "

Client

\n", + "

Client-85a16987-b1f9-11ed-8042-fa6ca111b70e

\n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
Connection method: Cluster objectCluster type: dask_kubernetes.KubeCluster
\n", + " Dashboard: /proxy/mock-jupyter-cluster-scheduler.default:8787/status\n", + "
\n", + "\n", + " \n", + " \n", + " \n", + "\n", + " \n", + "
\n", + "

Cluster Info

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

KubeCluster

\n", + "

mock-jupyter-cluster

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Dashboard: /proxy/mock-jupyter-cluster-scheduler.default:8787/status\n", + " \n", + " Workers: 0\n", + "
\n", + " Total threads: 0\n", + " \n", + " Total memory: 0 B\n", + "
\n", + "\n", + "
\n", + " \n", + "

Scheduler Info

\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

Scheduler

\n", + "

Scheduler-f6d55e0c-a7b1-4dfd-80b4-be0566b14cce

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Comm: tcp://10.28.1.12:8786\n", + " \n", + " Workers: 0\n", + "
\n", + " Dashboard: /proxy/10.28.1.12:8787/status\n", + " \n", + " Total threads: 0\n", + "
\n", + " Started: Just now\n", + " \n", + " Total memory: 0 B\n", + "
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "

Workers

\n", + "
\n", + "\n", + " \n", + "\n", + "
\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "\n", + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client = Client(cluster)\n", + "client" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now lets submit our workload again but this time to our cluster. Our function will be sent to our \"Jupyter\" worker which will then spawn another Dask cluster to run the workload. We don't have enough GPUs in our cluster to do this so it will trigger another scale operation." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 950 ms, sys: 9.1 ms, total: 959 ms\n", + "Wall time: 27.1 s\n" + ] + } + ], + "source": [ + "%%time\n", + "run_haversine().compute()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's write a small function which we can use to build up arbitrarily complex workloads. We can define how many stages we have, how many concurrent Dask clusters their should be, how quickly to vary width over time, etc." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "from random import randrange\n", + "\n", + "\n", + "def generate_workload(\n", + " stages=3, min_width=1, max_width=3, variation=1, input_workload=None\n", + "):\n", + " graph = [input_workload] if input_workload is not None else [run_haversine()]\n", + " last_width = min_width\n", + " for stage in range(stages):\n", + " width = randrange(\n", + " max(min_width, last_width - variation),\n", + " min(max_width, last_width + variation) + 1,\n", + " )\n", + " graph = [run_haversine(*graph) for _ in range(width)]\n", + " last_width = width\n", + " return run_haversine(*graph)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [], + "source": [ + "cluster.scale(3) # Let's also bump up our user cluster to show more users logging in." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To visualize our graphs let's check that we have `graphviz` installed." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Preparing transaction: ...working... done\n", + "Verifying transaction: ...working... done\n", + "Executing transaction: ...working... \n", + "\n", + "done\n" + ] + } + ], + "source": [ + "!mamba install -c conda-forge --quiet graphviz python-graphviz -y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's start with a small workload which will run a couple of stages and trigger a scale up." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "workload = generate_workload(stages=2, max_width=2)\n", + "workload.visualize()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is great we have multiple stages where one or two users are running workloads at the same time. Now lets chain a bunch of these workloads together to simulate varying demands over a larger period of time.\n", + "\n", + "We will also track the start and end times of the run so that we can grab the right data from Prometheus later." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "import datetime" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```{warning}\n", + "The next cell will take around 1h to run.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Task exception was never retrieved\n", + "future: .wait() done, defined at /opt/conda/envs/rapids/lib/python3.9/site-packages/distributed/client.py:2119> exception=AllExit()>\n", + "Traceback (most recent call last):\n", + " File \"/opt/conda/envs/rapids/lib/python3.9/site-packages/distributed/client.py\", line 2128, in wait\n", + " raise AllExit()\n", + "distributed.client.AllExit\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 2min 43s, sys: 3.04 s, total: 2min 46s\n", + "Wall time: 1h 18min 18s\n" + ] + } + ], + "source": [ + "%%time\n", + "start_time = (datetime.datetime.now() - datetime.timedelta(minutes=15)).strftime(\n", + " \"%Y-%m-%dT%H:%M:%SZ\"\n", + ")\n", + "try:\n", + " # Start with a couple of concurrent workloads\n", + " workload = generate_workload(stages=10, max_width=2)\n", + " # Then increase demand as more users appear\n", + " workload = generate_workload(\n", + " stages=5, max_width=5, min_width=3, variation=5, input_workload=workload\n", + " )\n", + " # Now reduce the workload for a longer period of time, this could be over a lunchbreak or something\n", + " workload = generate_workload(stages=30, max_width=2, input_workload=workload)\n", + " # Everyone is back from lunch and it hitting the cluster hard\n", + " workload = generate_workload(\n", + " stages=10, max_width=10, min_width=3, variation=5, input_workload=workload\n", + " )\n", + " # The after lunch rush is easing\n", + " workload = generate_workload(\n", + " stages=5, max_width=5, min_width=3, variation=5, input_workload=workload\n", + " )\n", + " # As we get towards the end of the day demand slows off again\n", + " workload = generate_workload(stages=10, max_width=2, input_workload=workload)\n", + " workload.compute()\n", + "finally:\n", + " client.close()\n", + " cluster.close()\n", + " end_time = (datetime.datetime.now() + datetime.timedelta(minutes=15)).strftime(\n", + " \"%Y-%m-%dT%H:%M:%SZ\"\n", + " )" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ok great, our large graph of workloads resulted in ~200 clusters launching throughout the run with varying capacity demands and took just over an hour to run." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analysis\n", + "\n", + "Let's explore the data we've been collecting with Prometheus to see how our cluster perforumed during our simulated workload. We could do this in [Grafana](https://grafana.com/), but instead let's stay in the notebook and use `prometheus-pandas`." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting prometheus-pandas\n", + " Downloading prometheus_pandas-0.3.2-py3-none-any.whl (6.1 kB)\n", + "Requirement already satisfied: numpy in /opt/conda/envs/rapids/lib/python3.9/site-packages (from prometheus-pandas) (1.23.5)\n", + "Requirement already satisfied: pandas in /opt/conda/envs/rapids/lib/python3.9/site-packages (from prometheus-pandas) (1.5.2)\n", + "Requirement already satisfied: python-dateutil>=2.8.1 in /opt/conda/envs/rapids/lib/python3.9/site-packages (from pandas->prometheus-pandas) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /opt/conda/envs/rapids/lib/python3.9/site-packages (from pandas->prometheus-pandas) (2022.6)\n", + "Requirement already satisfied: six>=1.5 in /opt/conda/envs/rapids/lib/python3.9/site-packages (from python-dateutil>=2.8.1->pandas->prometheus-pandas) (1.16.0)\n", + "Installing collected packages: prometheus-pandas\n", + "Successfully installed prometheus-pandas-0.3.2\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "! pip install prometheus-pandas" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Connect to the prometheus endpoint within our cluster." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [], + "source": [ + "from prometheus_pandas import query\n", + "\n", + "p = query.Prometheus(\"http://kube-prometheus-stack-prometheus.prometheus:9090\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Pending pods\n", + "\n", + "First let's see how long each of our Pods spent in a `Pending` phase. This is the amount of time users would have to wait for their work to start running when they create their Dask clusters." + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [], + "source": [ + "pending_pods = p.query_range(\n", + " 'kube_pod_status_phase{phase=\"Pending\",namespace=\"default\"}',\n", + " start_time,\n", + " end_time,\n", + " \"1s\",\n", + ").sum()" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "from dask.utils import format_time" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Average time for Pod creation." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'2.00 s'" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "format_time(pending_pods.median())" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'22.35 s'" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "format_time(pending_pods.mean())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "99th percentile time for Pod creation." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'326.00 s'" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "format_time(pending_pods.quantile(0.99))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These numbers seem great, the most common start time for a cluster is two seconds! With the average being around 20 seconds. If your cluster triggers Kubernetes to scale up you could be waiting for 5 minutes though. Let's see how many users would end up in that situation." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What percentage of users get workers in less than 2 seconds, 5 seconds, 60 seconds, etc?" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "59.70873786407767" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from scipy import stats\n", + "\n", + "stats.percentileofscore(pending_pods, 2.01)" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "72.00647249190939" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "stats.percentileofscore(pending_pods, 5.01)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "91.10032362459548" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "stats.percentileofscore(pending_pods, 60.01)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ok this looks pretty reasonable. Nearly 75% of users get a cluster in less than 5 seconds, and over 90% get it in under a minute. But if you're in the other 10% you may have to wait for 5 minutes." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's bucket this data to see the distribution of startup times visually." + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'Pods')" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAHFCAYAAAAUpjivAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA84ElEQVR4nO3de3RU1f3//9eQy+RCEkICGSIBEVHBAEqiXKwkSAhyERAtRbRAkYoF+ZICUpBVCa0NYBWwoGgtAtVSbFUsS5EmIIS7QhAFpEgVEDQhAoFwnQxh//7wl/PpEAJhSJhweD7WylrMPnvO2fs9E/Nyn3NmHMYYIwAAAJuq5e8BAAAAVCfCDgAAsDXCDgAAsDXCDgAAsDXCDgAAsDXCDgAAsDXCDgAAsDXCDgAAsDXCDgAAsDXCDnAB8+fPl8PhsH5CQkLkcrnUqVMnTZkyRYWFhdV6/MGDB6t27dqX/bwXXnhBDodDn3zyiVf7uXPnVLduXTkcDu3atctrW0lJicLCwtS3b98rGnOZvXv3yuFw6IUXXqiS/V2uzMxMr9cuODhYTZo00ahRo3T06NEqO47D4VBmZmaV7c8Xq1atksPh0KpVq6y2pUuXXta4Fi5cqJkzZ15wW02YI1AVCDvARcybN08bNmxQTk6OXn75Zd1xxx2aNm2amjdvruXLl/t7eOV06tRJkrRy5Uqv9s8//1xFRUUKDw8vt+2TTz7R6dOnrefaxbJly7RhwwZ9+OGH6tOnj2bNmqVu3brJTt+Q06ZNG23YsEFt2rSx2pYuXarJkydXeh8XCzsbNmzQ0KFDr3SYgN8RdoCLSExMVLt27XTvvffqoYce0owZM/TFF18oPDxcffv21cGDB/09RC933nmn6tSp4/V/+tKPKwDx8fHq1atXubBT1vdKw44xRqdPn76ifVTWqVOnLtknKSlJ7dq1U5cuXTRjxgw99thj2rhxo9avX38VRnh1REZGql27doqMjKyW/bdr104NGzasln0DVxNhB7hMjRo10osvvqjjx4/rtddes9o3b96s/v3768Ybb1RoaKhuvPFGPfLII9q3b5/X80+dOqWxY8eqSZMmCgkJUd26dZWcnKy///3vFz3uunXrFBsbq549e+rkyZMX7FOrVi117NhR69at09mzZ632VatWKTU1VSkpKRcMQvXq1dPtt98uSTpy5IiGDx+uG264QcHBwbrppps0ceJEud1ur+c5HA499dRTevXVV9W8eXM5nU4tWLDgguPyeDwaNGiQateurQ8++EDSj+HolVde0R133KHQ0FBFR0fr4Ycf1jfffOP13NTUVCUmJmr16tXq0KGDwsLCNGTIkIvW6kLatWsnSdbrUdl5FhcX65e//KViYmJUu3Zt3X///frqq68ueTxjjOLi4jRixAirrbS0VNHR0apVq5ZXUJ4+fboCAwOt02yVfS+dfxpr8ODBevnllyXJ61Te3r17LzjG1NRUffjhh9q3b59X/zLnn8YqO7378ccfWzWJjIzUwIEDdfLkSRUUFKhfv36qU6eOGjRooLFjx8rj8Xgds6SkRM8995xuu+02OZ1O1atXT7/4xS/0ww8/ePX7+OOPlZqaqpiYGIWGhqpRo0Z66KGHKhV0gfMF+nsAwLWoe/fuCggI0OrVq622vXv36tZbb1X//v1Vt25d5efna86cObrrrrv05ZdfKjY2VpI0evRovfnmm3ruued055136uTJk9q+fbsOHz5c4fH+8Y9/aODAgRoyZIhmzZqlgICACvt26tRJS5Ys0aZNm9S+fXudO3dOq1ev1rRp09SxY0cVFhbqyy+/VIsWLVRSUqINGzaoZ8+ecjgcOnPmjDp16qSvv/5akydPVqtWrbRmzRpNmTJFW7du1Ycffuh1rPfff19r1qzRs88+K5fLpfr165cbz9GjR9W3b1/t3LlTubm5SkpKkiQNGzZM8+fP1//7f/9P06ZN05EjR/S73/1OHTp00Oeff664uDhrH/n5+Xrsscc0btw4ZWVlqVaty///tP/+97+SpHr16lV6nsYY9enTR+vXr9ezzz6ru+66S+vWrVO3bt0ueTyHw6H77rvP63Tn5s2bdfToUYWGhmrFihUaMGCAJGn58uVKSkpSnTp1JFX+vXS+3/72tzp58qTeeecdbdiwwWpv0KDBBfu/8soreuKJJ/T1119r8eLFly7i/2/o0KHq27evFi1apM8++0zPPPOMzp49q127dqlv37564okntHz5ck2bNk3x8fEaPXq0pB+vHevdu7fWrFmjcePGqUOHDtq3b58mTZqk1NRUbd68WaGhodq7d6969Oihe++9V2+88Ybq1Kmj7777TsuWLbOuMQMuiwFQzrx584wks2nTpgr7xMXFmebNm1e4/ezZs+bEiRMm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ztixY/XAAw+oUaNGKiws1HPPPafi4mINGjRIDodDGRkZysrKUrNmzdSsWTNlZWUpLCxMAwYMkCRFRUXp8ccf15gxYxQTE6O6detq7NixatmypXV3FgAAuL75NewcOHBAjzzyiA4dOqR69eqpXbt22rhxoxo3bixJGjdunE6fPq3hw4erqKhIbdu2VXZ2tiIiIqx9zJgxQ4GBgerXr59Onz6tzp07a/78+QoICPDXtAAAQA3i17CzaNGii253OBzKzMxUZmZmhX1CQkI0a9YszZo1q4pHBwAA7MDvn7MDAABQnQg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1gg7AADA1mpM2JkyZYocDocyMjKsNmOMMjMzFR8fr9DQUKWmpmrHjh1ez3O73Ro5cqRiY2MVHh6uXr166cCBA1d59AAAoKaqEWFn06ZN+vOf/6xWrVp5tT///POaPn26Zs+erU2bNsnlcqlLly46fvy41ScjI0OLFy/WokWLtHbtWp04cUI9e/ZUaWnp1Z4GAACogfwedk6cOKFHH31Ur7/+uqKjo612Y4xmzpypiRMnqm/fvkpMTNSCBQt06tQpLVy4UJJ07NgxzZ07Vy+++KLS0tJ055136q233tK2bdu0fPlyf00JAADUIIH+HsCIESPUo0cPpaWl6bnnnrPa9+zZo4KCAqWnp1ttTqdTKSkpWr9+vYYNG6a8vDx5PB6vPvHx8UpMTNT69evVtWvXCx7T7XbL7XZbj4uLiyVJHo9HHo+nyuZWti9nLVNl+6zoGHZU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YWEaMGCAJCkqKkqPP/64xowZo5iYGNWtW1djx45Vy5YtlZaW5s+pAQCAGsKvYefgwYP6+c9/rvz8fEVFRalVq1ZatmyZunTpIkkaN26cTp8+reHDh6uoqEht27ZVdna2IiIirH3MmDFDgYGB6tevn06fPq3OnTtr/vz5CggI8Ne0AABADeLXsDN37tyLbnc4HMrMzFRmZmaFfUJCQjRr1izNmjWrikcHAADsoMZdswMAAFCVfAo7y5Yt09q1a63HL7/8su644w4NGDBARUVFVTY4AACAK+VT2Hn66aete9u3bdumMWPGqHv37vrmm2+8Pr8GAADA33y6ZmfPnj1q0aKFJOndd99Vz549lZWVpS1btqh79+5VOkAAAIAr4dPKTnBwsPURzcuXL7e+m6pu3bqV/jRDAACAq8GnlZ2f/OQnGj16tO655x59+umnevvttyVJX331lRo2bFilAwQAALgSPq3szJ49W4GBgXrnnXc0Z84c3XDDDZKkjz76SPfff3+VDhAAAOBK+LSy06hRI33wwQfl2mfMmHHFAwIAAKhKlQ47l3MtTlV+czgAAMCVqHTYqVOnjhyOyn1zd2lpqc8DAgAAqEqVDjsrV660/r13716NHz9egwcPVvv27SVJGzZs0IIFCzRlypSqHyUAAICPKh12UlJSrH//7ne/0/Tp0/XII49Ybb169VLLli315z//WYMGDaraUQIAAPjIp7uxNmzYoOTk5HLtycnJ+vTTT694UAAAAFXFp7CTkJCgV199tVz7a6+9poSEhCseFAAAQFXx6dbzGTNm6KGHHtK///1vtWvXTpK0ceNGff3113r33XerdIAAAABXwqeVne7du2v37t3q1auXjhw5osOHD6t379766quv+G4sAABQo/i0siNJDRs2VFZWVlWOBQAAoMr5HHaOHj2quXPnaufOnXI4HGrRooWGDBmiqKioqhwfAADAFfHpNNbmzZvVtGlTzZgxQ0eOHNGhQ4c0ffp0NW3aVFu2bKnqMQIAAPjMp5WdX//61+rVq5def/11BQb+uIuzZ89q6NChysjI0OrVq6t0kAAAAL7yKexs3rzZK+hIUmBgoMaNG3fBz98BAADwF59OY0VGRurbb78t175//35FRERc8aAAAACqik9h52c/+5kef/xxvf3229q/f78OHDigRYsWaejQoV5fIQEAAOBv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brdGjhyp2NhYhYeHq1evXjpw4MBVnAUAAKjJ/Bp2Tp48qdatW2v27NkX3P78889r+vTpmj17tjZt2iSXy6UuXbro+PHjVp+MjAwtXrxYixYt0tq1a3XixAn17NlTpaWlV2saAACgBgv058G7deumbt26XXCbMUYzZ87UxIkT1bdvX0nSggULFBcXp4ULF2rYsGE6duyY5s6dqzfffFNpaWmSpLfeeksJCQlavny5unbtetXmAgAAaia/hp2L2bNnjwoKCpSenm61OZ1OpaSkaP369Ro2bJjy8vLk8Xi8+sTHxysxMVHr16+vMOy43W653W7rcXFxsSTJ4/HI4/FU2RzK9uWsZapsnxUdw47K5mbnOVYXauc7auc7auc7auebytarxoadgoICSVJcXJxXe1xcnPbt22f1CQ4OVnR0dLk+Zc+/kClTpmjy5Mnl2rOzsxUWFnalQy/n98nnqnyfZZYuXVpt+64pcnJy/D2Eaxa18x218x218x21uzynTp2qVL8aG3bKOBwOr8fGmHJt57tUnwkTJmj06NHW4+LiYiUkJCg9PV2RkZFXNuD/4fF4lJOTo99uriX3uYuP2VfbM+17qq6sfl26dFFQUJC/h3NNoXa+o3a+o3a+o3a+KTszcyk1Nuy4XC5JP67eNGjQwGovLCy0VntcLpdKSkpUVFTktbpTWFioDh06VLhvp9Mpp9NZrj0oKKha3mTucw65S6sn7FwPvxTV9bpcD6id76id76id76jd5alsrWrs5+w0adJELpfLa0mvpKREubm5VpBJSkpSUFCQV5/8/Hxt3779omEHAABcP/y6snPixAn997//tR7v2bNHW7duVd26ddWoUSNlZGQoKytLzZo1U7NmzZSVlaWwsDANGDBAkhQVFaXHH39cY8aMUUxMjOrWrauxY8eqZcuW1t1ZAADg+ubXsLN582Z16tTJelx2Hc2gQYM0f/58jRs3TqdPn9bw4cNVVFSktm3bKjs7WxEREdZzZsyYocDAQPXr10+nT59W586dNX/+fAUEBFz1+QAAgJrHr2EnNTVVxlR8W7bD4VBmZqYyMzMr7BMSEqJZs2Zp1qxZ1TBCAABwraux1+wAAABUBcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwNcIOAACwtUB/DwBX5sbxH1br/vdO7VGt+wcAoLqxsgMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGyNsAMAAGwt0N8DQM124/gPq3X/e6f2qNb9AwDAyg4AALA1wg4AALA1wg4AALA1wg4AALA1wg4AALA1wg4AALA1wg4AALA1PmcHqKGu5DOOnAFGz98tJWb+W+5SxwX78BlHAK4XtlnZeeWVV9SkSROFhIQoKSlJa9as8feQAABADWCLlZ23335bGRkZeuWVV3TPPffotddeU7du3fTll1+qUaNG/h4ebKq6P136WmaHT96+2KpYTcaKHVCeLVZ2pk+frscff1xDhw5V8+bNNXPmTCUkJGjOnDn+HhoAAPCza35lp6SkRHl5eRo/frxXe3p6utavX++nUaGyLrYCUJnrTi6G/8O9OFamAFwvrvmwc+jQIZWWliouLs6rPS4uTgUFBRd8jtvtltvtth4fO3ZMknTkyBF5PJ4qG5vH49GpU6cU6Kml0nPX3nK4vwWeMzp16pzP9Tt8+HA1jOr/BJ49Wa37vxJXWruarjpf22v997a63/cXU1a7w4cPKygoyG/juBZRO98cP35ckmSMuWi/az7slHE4vP+jZIwp11ZmypQpmjx5crn2Jk2aVMvY4LsBV/Dc2BerbBjXpCupXU13vb+2F0NtcD06fvy4oqKiKtx+zYed2NhYBQQElFvFKSwsLLfaU2bChAkaPXq09fjcuXM6cuSIYmJiKgxIviguLlZCQoL279+vyMjIKtvv9YL6+Y7a+Y7a+Y7a+Y7a+cYYo+PHjys+Pv6i/a75sBMcHKykpCTl5OTowQcftNpzcnLUu3fvCz7H6XTK6XR6tdWpU6faxhgZGcmb9wpQP99RO99RO99RO99Ru8t3sRWdMtd82JGk0aNH6+c//7mSk5PVvn17/fnPf9a3336rJ5980t9DAwAAfmaLsPOzn/1Mhw8f1u9+9zvl5+crMTFRS5cuVePGjf09NAAA4Ge2CDuSNHz4cA0fPtzfw/DidDo1adKkcqfMUDnUz3fUznfUznfUznfUrno5zKXu1wIAALiG2eITlAEAACpC2AEAALZG2AEAALZG2AEAALZG2KlGr7zyipo0aaKQkBAlJSVpzZo1/h6S361evVoPPPCA4uPj5XA49P7773ttN8YoMzNT8fHxCg0NVWpqqnbs2OHVx+12a+TIkYqNjVV4eLh69eqlAwcOXMVZXH1TpkzRXXfdpYiICNWvX199+vTRrl27vPpQu4rNmTNHrVq1sj6wrX379vroo4+s7dSucqZMmSKHw6GMjAyrjdpVLDMzUw6Hw+vH5XJZ26ndVWRQLRYtWmSCgoLM66+/br788kszatQoEx4ebvbt2+fvofnV0qVLzcSJE827775rJJnFixd7bZ86daqJiIgw7777rtm2bZv52c9+Zho0aGCKi4utPk8++aS54YYbTE5OjtmyZYvp1KmTad26tTl79uxVns3V07VrVzNv3jyzfft2s3XrVtOjRw/TqFEjc+LECasPtavYkiVLzIcffmh27dpldu3aZZ555hkTFBRktm/fboyhdpXx6aefmhtvvNG0atXKjBo1ymqndhWbNGmSuf32201+fr71U1hYaG2ndlcPYaea3H333ebJJ5/0arvtttvM+PHj/TSimuf8sHPu3DnjcrnM1KlTrbYzZ86YqKgo8+qrrxpjjDl69KgJCgoyixYtsvp89913platWmbZsmVXbez+VlhYaCSZ3NxcYwy180V0dLT5y1/+Qu0q4fjx46ZZs2YmJyfHpKSkWGGH2l3cpEmTTOvWrS+4jdpdXZzGqgYlJSXKy8tTenq6V3t6errWr1/vp1HVfHv27FFBQYFX3ZxOp1JSUqy65eXlyePxePWJj49XYmLidVXbY8eOSZLq1q0ridpdjtLSUi1atEgnT55U+/btqV0ljBgxQj169FBaWppXO7W7tN27dys+Pl5NmjRR//799c0330iidlebbT5BuSY5dOiQSktLy33relxcXLlvZ8f/KavNheq2b98+q09wcLCio6PL9bleamuM0ejRo/WTn/xEiYmJkqhdZWzbtk3t27fXmTNnVLt2bS1evFgtWrSw/mhQuwtbtGiRtmzZok2bNpXbxvvu4tq2bau//vWvuuWWW3Tw4EE9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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ax = pending_pods.hist(bins=range(0, 600, 30))\n", + "ax.set_title(\"Dask Worker Pod wait times\")\n", + "ax.set_xlabel(\"Seconds\")\n", + "ax.set_ylabel(\"Pods\")" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'Pods')" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAj0AAAHFCAYAAAAZuEjoAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAABCc0lEQVR4nO3deXwV9b3/8feBhENWyEK2ihGRsgZUomxKgkCURUGwiuiFiFaoiFJEKnqV4FU2FWhB0VoKiOVCa4VSWQNCEAGFCBUoRVRQ0IRICAQCZOP7+8Nf5nLIQnI44STM6/l4nIfOd74z853PmSRvZjnHYYwxAgAAuMrV8fYAAAAArgRCDwAAsAVCDwAAsAVCDwAAsAVCDwAAsAVCDwAAsAVCDwAAsAVCDwAAsAVCDwAAsAVCDypt/vz5cjgc1qt+/fqKiopSt27dNHnyZGVlZVXr9pOTkxUYGFjl5V5//XU5HA599tlnLu3nz59XaGioHA6H9u/f7zKvoKBA/v7+GjBgwGWNucShQ4fkcDj0+uuve2R9VZWSkuLy3tWrV09NmjTR008/rRMnTnhsOw6HQykpKR5bnzs2btwoh8OhjRs3Wm0rV66s0rgWLVqkmTNnljmvJuyjOwoLC9WiRQtNmTLFarv4Z/rC19ixY63jdv78+R4bx1tvveXR9V1KcnKyrrvuumrfzqRJk7Rs2TK3l8/JyVHDhg0vax24NB9vDwC1z7x589SiRQsVFhYqKytLmzdv1tSpU/X6669ryZIl6tGjh7eH6KJbt26SpA0bNqhDhw5W+7/+9S/l5OQoICBAGzZsUPPmza15n332mc6ePWste7VYvXq1GjRooFOnTmnlypX6/e9/r88//1xbtmyRw+Hw9vA84uabb9bWrVvVqlUrq23lypV68803Kx1WFi1apD179mj06NGl5m3dulXXXHONh0Z75bz11lvKycnRqFGjSs0r+Zm+UExMjCIjI7V161Y1bdrUo+MIDw9XcnKyx9ZZkRdffFFPP/10tW9n0qRJuu+++9S/f3+3lg8JCdFvf/tbPfvss+rdu7fq1avn2QFCEqEHbmjTpo3i4+Ot6YEDB+q3v/2tbrvtNg0YMEAHDhxQZGSkF0fo6qabblLDhg21ceNGPffcc1b7xo0bFRMTo4SEBG3YsEEjRoxwmSfpskOPMUbnzp27rHVU1pkzZ+Tv719hn/bt2ys8PFyS1LNnT2VnZ2vhwoXasmWLunTpciWGWe2Cg4PVsWPHalt/da67uhQVFem1117TsGHDFBAQUGr+xT/TF6rM/lbm2PMWTwa26jZixAi98sor+uCDDzR48GBvD+eqxOUteMS1116rN954Q6dOndI777xjte/YsUODBg3SddddJz8/P1133XV68MEH9d1337ksf+bMGY0dO1ZNmjRR/fr1FRoaqvj4eP3v//5vhdv99NNPFR4err59+yovL6/MPnXq1FHXrl316aefqqioyGrfuHGjEhMTlZCQ4HIppGReo0aN1Lp1a0nS8ePH9cQTT+gXv/iF6tWrp+uvv14vvPCC8vPzXZZzOBx68skn9fbbb6tly5ZyOp1asGBBmeMqLCzU0KFDFRgYqI8++kjSzyHprbfe0o033ig/Pz+FhITovvvu07fffuuybGJiotq0aaNNmzapc+fO8vf317BhwyqsVVlK/qCVvB+V3c/c3Fz9+te/VlhYmAIDA3XXXXfpq6++uuT2jDGKjIzUyJEjrbbi4mKFhISoTp06Onr0qNU+ffp0+fj4WJffKnssXXx5Kzk5WW+++aYkuVy+OXToUJljTExM1IoVK/Tdd9+59C9x8eWtkktEH3/8sVWT4OBgDRkyRHl5ecrMzNT999+vhg0bKjo6WmPHjlVhYaHLNgsKCvTKK6+oRYsWcjqdatSokR555BH99NNPLv0+/vhjJSYmKiwsTH5+frr22ms1cOBAnTlzpsK6L1++XD/88IP+67/+q8J+Fyvr8lbJpdIvvvhC9913n0JCQqxg8e2332rQoEGKiYmR0+lUZGSkunfvrl27dkmSrrvuOu3du1dpaWlWXS916ankZ2revHlq3ry5/Pz8FB8fr23btskYo9dee01NmjRRYGCg7rjjDn399dcuy5d1eatknQsXLlTLli3l7++vdu3aWT+HFS17YQ0uXF9eXp4WLFhg7VdiYqI1PzMzU8OHD9c111xjXVqeOHGiy+8jSYqMjFTPnj319ttvV1gTuI8zPfCY3r17q27dutq0aZPVdujQITVv3lyDBg1SaGioMjIyNGfOHN1yyy3697//bZ11GDNmjBYuXKhXXnlFN910k/Ly8rRnzx5lZ2eXu72//vWvGjJkiIYNG6ZZs2apbt265fbt1q2bli9fru3bt6tTp046f/68Nm3apKlTp6pr167KysrSv//9b7Vq1UoFBQXaunWr+vbtK4fDoXPnzqlbt2765ptvNHHiRLVt21affPKJJk+erF27dmnFihUu21q2bJk++eQTvfTSS4qKilJERESp8Zw4cUIDBgzQvn37lJaWpvbt20uShg8frvnz5+upp57S1KlTdfz4cb388svq3Lmz/vWvf7mcQcvIyNDDDz+scePGadKkSapTp+r/hin5A9GoUaNK76cxRv3799eWLVv00ksv6ZZbbtGnn36qXr16XXJ7DodDd9xxh9atW2e17dixQydOnJCfn5/Wr19v/Qt33bp1at++vRo2bCip8sfSxV588UXl5eXpgw8+0NatW6326OjoMvu/9dZbevzxx/XNN99o6dKlly7i//fYY49pwIABWrx4sXbu3Knnn39eRUVF2r9/vwYMGKDHH39c69at09SpUxUTE6MxY8ZI+vnesn79+umTTz7RuHHj1LlzZ3333XeaMGGCEhMTtWPHDvn5+enQoUPq06ePbr/9dv35z39Ww4YN9cMPP2j16tXWPWjlWbFihSIiIlwu+V2ouLi41B9gH5+K/zwMGDBAgwYN0ogRI6x/cPTu3VvFxcWaNm2arr32Wh07dkxbtmyxguvSpUt13333qUGDBnrrrbckSU6n85K1/eijj7Rz505NmTJFDodDv/vd79SnTx8NHTpU3377rWbPnq2TJ09qzJgxGjhwoHbt2nXJy7UrVqzQ9u3b9fLLLyswMFDTpk3Tvffeq/379+v666+/5JgutHXrVt1xxx3q1q2bXnzxRUk/n3GUfg48t956q+rUqaOXXnpJTZs21datW/XKK6/o0KFDmjdvnsu6EhMTNX78eJ04ccI69uFBBqikefPmGUlm+/bt5faJjIw0LVu2LHd+UVGROX36tAkICDC///3vrfY2bdqY/v37V7j9oUOHmoCAAGOMMVOmTDF169Y1U6dOrdTYd+3aZSSZSZMmGWOMSU9PN5LMf/7zH2vcs2fPNsYYk5aWZiSZt956yxhjzNtvv20kmb/+9a8u65w6daqRZNauXWu1STINGjQwx48fd+l78OBBI8m89tpr5uDBg6ZVq1amVatW5tChQ1afrVu3GknmjTfecFn28OHDxs/Pz4wbN85qS0hIMJLM+vXrK7X/EyZMMJJMZmamKSwsNDk5Oeb99983fn5+pnHjxubs2bOV3s9Vq1YZSS7vnzHGvPrqq0aSmTBhQoVj+dOf/mQkme+//94YY8wrr7xiWrRoYe655x7zyCOPGGOMKSgoMAEBAeb5558vdz3lHUsbNmwwksyGDRustpEjR5qq/Lrr06ePiY2NLXPexftY8nMxatQol379+/c3ksz06dNd2m+88UZz8803W9P/+7//aySZv//97y79tm/f7nIcfvDBB0aS2bVrV6X3o0TLli3NXXfdVaq9ZOxlvQoLC63jdt68edYyJcfSSy+95LKuY8eOGUlm5syZFY6ldevWJiEhodJjl2SioqLM6dOnrbZly5YZSebGG28058+ft9pnzpxpJJkvv/zSahs6dGip91KSiYyMNLm5uVZbZmamqVOnjpk8eXKFyxrzfzW4UEBAgBk6dGipvsOHDzeBgYHmu+++c2l//fXXjSSzd+9el/bU1FQjyaxatap0MXDZuLwFjzLGuEyfPn1av/vd73TDDTfIx8dHPj4+CgwMVF5envbt22f1u/XWW7Vq1So999xz2rhxo86ePVvu+ocPH64JEyZo0aJFGjduXKXG1bZtW4WFhVmXPDZu3KioqCjr5uWuXbtqw4YN1jzp/+7n+fjjjxUQEKD77rvPZZ0lN2KuX7/epf2OO+5QSEhImeP44osv1LFjR0VGRurTTz9VbGysNe+jjz6Sw+HQww8/rKKiIusVFRWldu3alboEFxISojvuuKNS+18iKipKvr6+CgkJ0cMPP6ybb75Zq1evVv369Su9nyV1euihh1z6VfYehJIb3UvO9qSmpqpnz57q0aOHUlNTJf38L+e8vDyXm+Ireyx5S9++fV2mW7ZsKUnq06dPqfYLL8l99NFHatiwoe6++26X9/3GG29UVFSU9b7feOONqlevnh5//HEtWLCg1CXPivz4449lnnEs8d5772n79u0ur0ud6Rk4cKDLdGhoqJo2barXXntN06dP186dO3X+/PlKj7Ei3bp1c7kXqaS2vXr1cjmjU9J+8SXP8tYZFBRkTUdGRioiIqJSy1bFRx99pG7duikmJsbl/S05M5qWlubSv+R9+uGHHzw6DvyM0AOPycvLU3Z2tmJiYqy2wYMHa/bs2Xrssce0Zs0aff7559q+fbsaNWrkEmz+8Ic/6He/+52WLVumbt26KTQ0VP3799eBAwdctlFQUKAlS5aodevWlbqcUsLhcCghIUGffvqpCgsLtWHDBiUkJFjzExISlJaWJmOMNmzYoKioKOtpluzsbEVFRZU6XR4RESEfH59Sl+DKu2wi/fwH/ujRo3rsscdKnbo+evSodc+Lr6+vy2vbtm06duxYpbdTnnXr1mn79u3atWuXjh07ps2bN1uXPCq7n9nZ2fLx8VFYWJhLv6ioqEqNITY2Vk2bNtW6det05swZbd261Qo9R44c0f79+7Vu3Tr5+fmpc+fO1nKVPZa8JTQ01GW65OmbstovvLn96NGjOnHihOrVq1fqfc/MzLTe95KaRUREaOTIkWratKmaNm2q3//+95cc29mzZ1W/fv1y57ds2VLx8fEur0u5+PhzOBxav3697rzzTk2bNk0333yzGjVqpKeeekqnTp265PoqUpXaSqrUwwMXH7/Sz5faPH0sHT16VP/85z9Lvbcl9wte/HNd8j7VhGP6asQ9PfCYFStWqLi42LqB7+TJk/roo480YcIEl6em8vPzdfz4cZdlAwICNHHiRE2cOFFHjx61zvrcfffd+s9//mP1czqd2rBhg+6880716NFDq1evLvesysW6deumDz/8UJ999pl1r0qJhIQEHTt2TOnp6dq2bZvuvfdea15YWJg+++wzGWNcAkFWVpaKiopK3UtS0b0Ezz77rL755hsNGTJERUVFGjJkiDUvPDxcDodDn3zySZn3OVzc5s4j5u3atSv33pfK7mdYWJiKioqUnZ3t8ocjMzOz0uPo3r27/vGPfygtLU3nz59XYmKigoKCFBMTo9TUVK1bt0633367tc9VOZZqm/DwcIWFhWn16tVlzr/wbMTtt9+u22+/XcXFxdqxY4dmzZql0aNHKzIyUoMGDapwG56uU1nHX2xsrObOnStJ+uqrr/TXv/5VKSkpKigoqJU359avX7/UTfxS6aBSkfDwcLVt21avvvpqmfMv/EeiJOt9Ku/nFJeHMz3wiO+//15jx45VgwYNNHz4cEk//1I0xpT6Y/2nP/1JxcXF5a4rMjJSycnJevDBB7V///5ST6bcdNNNSktL05EjR5SYmFjpD0UsuVw1Y8YMnTx50uXpitatWyssLEyTJ0+2bugt0b17d50+fbrUh4a999571vzKqlOnjt555x09/fTTSk5O1pw5c6x5ffv2lTFGP/zwQ6l/dcfHxysuLq7S23FHZfezpDZ/+ctfXPotWrSo0tvq0aOHjh49qpkzZ6pjx47WH/bu3btr6dKl2r59u8ulLXePpRIly1X2X8/V8S/+8vTt21fZ2dkqLi4u832/8POjStStW1cdOnSwnkr74osvKtxGixYt9M0331TL+Mvzy1/+Uv/93/+tuLg4l/Fdydperuuuu05ZWVkuTxUWFBRozZo1pfqWt199+/bVnj171LRp0zLf34tDT8lly/JuOsfl4UwPqmzPnj3WdemsrCx98sknmjdvnurWraulS5eqUaNGkn5+eqFr16567bXXFB4eruuuu05paWmaO3duqUs7HTp0UN++fdW2bVuFhIRo3759WrhwoTp16lTmUyktW7bUJ598oh49eqhr165at27dJT8wrnXr1oqIiLDGWHL9X/r5j2rXrl2tp3UuDD1DhgzRm2++qaFDh+rQoUOKi4vT5s2bNWnSJPXu3dutD2N84403FBQUpCeeeEKnT5/Ws88+qy5duujxxx/XI488oh07dqhr164KCAhQRkaGNm/erLi4OP3mN7+p8rYqq7L7mZSUpK5du2rcuHHKy8tTfHy8Pv30Uy1cuLDS27rjjjvkcDi0du1aTZw40Wrv0aOHhg4dav1/iaocS2UpCYxTp05Vr169VLduXbVt27bcD4CLi4vThx9+qDlz5qh9+/aqU6dOpS75uGPQoEH6y1/+ot69e+vpp5/WrbfeKl9fXx05ckQbNmxQv379dO+99+rtt9/Wxx9/rD59+ujaa6/VuXPn9Oc//1mSLnkMJiYm6uWXX67Wz9P58ssv9eSTT+pXv/qVmjVrpnr16unjjz/Wl19+6XJ2Li4uTosXL9aSJUt0/fXXq379+tUe6N31wAMP6KWXXtKgQYP07LPP6ty5c/rDH/5QZtCOi4vTxo0b9c9//lPR0dEKCgpS8+bN9fLLLys1NVWdO3fWU089pebNm+vcuXM6dOiQVq5cqbffftvld9e2bdsUFhZWY2tS63ntFmrUOhc/6VGvXj0TERFhEhISzKRJk0xWVlapZY4cOWIGDhxoQkJCTFBQkLnrrrvMnj17TGxsrMuTDs8995yJj483ISEhxul0muuvv9789re/NceOHbP6XPj01oXrb9GihbnuuuvMN998c8l9uP/++40kc99995WaV/Lkxy9+8YtS87Kzs82IESNMdHS08fHxMbGxsWb8+PHm3LlzLv0kmZEj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U7eytW7dWhkZGdZr9+7d1jxqVracnBx16dJFvr6+WrVqlf7973/rjTfecPm2BI/UzqBa3HrrrWbEiBEubS1atDDPPfecl0ZUs0kyS5cutabPnz9voqKizJQpU6y2c+fOmQYNGpi3337bCyOsmbKysowkk5aWZoyhblUREhJi/vSnP1GzSzh16pRp1qyZSU1NNQkJCebpp582xnCslWfChAmmXbt2Zc6jZuX73e9+Z2677bZy53uqdpzpqQYFBQVKT09XUlKSS3tSUpK2bNnipVHVLgcPHlRmZqZLDZ1OpxISEqjhBU6ePClJCg0NlUTdKqO4uFiLFy9WXl6eOnXqRM0uYeTIkerTp4969Ojh0k7dynfgwAHFxMSoSZMmGjRokL799ltJ1Kwiy5cvV3x8vH71q18pIiJCN910k959911rvqdqR+ipBseOHVNxcXGpb3mPjIws9W3wKFtJnahh+YwxGjNmjG677Ta1adNGEnWryO7duxUYGCin06kRI0Zo6dKlatWqFTWrwOLFi/XFF19o8uTJpeZRt7J16NBB7733ntasWaN3331XmZmZ6ty5s7Kzs6lZBb799lvNmTNHzZo105o1azRixAg99dRTeu+99yR57ni7ar6GoiZyOBwu08aYUm2oGDUs35NPPqkvv/xSmzdvLjWPupXWvHlz7dq1SydOnNDf//53DR06VGlpadZ8aubq8OHDevrpp7V27VrVr1+/3H7UzVWvXr2s/4+Li1OnTp3UtGlTLViwQB07dpREzcpy/vx5xcfHa9KkSZKkm266SXv37tWcOXM0ZMgQq9/l1o4zPdUgPDxcdevWLZU+s7KySqVUlK3kaQdqWLZRo0Zp+fLl2rBhg6655hqrnbqVr169errhhhsUHx+vyZMnq127dvr9739PzcqRnp6urKwstW/fXj4+PvLx8VFaWpr+8Ic/yMfHx6oNdatYQECA4uLidODAAY61CkRHR6tVq1YubS1btrQe/vFU7Qg91aBevXpq3769UlNTXdpTU1PVuXNnL42qdmnSpImioqJcalhQUKC0tDRb19AYoyeffFIffvihPv74YzVp0sRlPnWrPGOM8vPzqVk5unfvrt27d2vXrl3WKz4+Xg899JB27dql66+/nrpVQn5+vvbt26fo6GiOtQp06dKl1MdvfPXVV4qNjZXkwd9tbtxkjUpYvHix8fX1NXPnzjX//ve/zejRo01AQIA5dOiQt4dWY5w6dcrs3LnT7Ny500gy06dPNzt37jTfffedMcaYKVOmmAYNGpgPP/zQ7N692zz44IMmOjra5Obmennk3vOb3/zGNGjQwGzcuNFkZGRYrzNnzlh9qFtp48ePN5s2bTIHDx40X375pXn++edNnTp1zNq1a40x1KyyLnx6yxjqVpZnnnnGbNy40Xz77bdm27Ztpm/fviYoKMj63U/Nyvb5558bHx8f8+qrr5oDBw6Yv/zlL8bf39+8//77Vh9P1I7QU43efPNNExsba+rVq2duvvlm67Fi/GzDhg1GUqnX0KFDjTE/P6I4YcIEExUVZZxOp+natavZvXu3dwftZWXVS5KZN2+e1Ye6lTZs2DDrZ7FRo0ame/fuVuAxhppV1sWhh7qV9sADD5jo6Gjj6+trYmJizIABA8zevXut+dSsfP/85z9NmzZtjNPpNC1atDB//OMfXeZ7onYOY4xx+3wUAABALcE9PQAAwBYIPQAAwBYIPQAAwBYIPQAAwBYIPQAAwBYIPQAAwBYIPQAAwBYIPQBQBcnJyerfv7+3hwHADYQeAF6RlZWl4cOH69prr5XT6VRUVJTuvPNObd261dtDA3CV8vH2AADY08CBA1VYWKgFCxbo+uuv19GjR7V+/XodP37c20MDcJXiTA+AK+7EiRPavHmzpk6dqm7duik2Nla33nqrxo8frz59+kiSTp48qccff1wREREKDg7WHXfcoX/9618u61m+fLni4+NVv359hYeHa8CAAda8nJwcDRkyRCEhIfL391evXr104MABa/78+fPVsGFDrVmzRi1btlRgYKDuuusuZWRkWH2Ki4s1ZswYNWzYUGFhYRo3bpwu/uaeDz74QHFxcfLz81NYWJh69OihvLy86igbgMtE6AFwxQUGBiowMFDLli1Tfn5+qfnGGPXp00eZmZlauXKl0tPTdfPNN6t79+7WmaAVK1ZowIAB6tOnj3bu3Kn169crPj7eWkdycrJ27Nih5cuXa+vWrTLGqHfv3iosLLT6nDlzRq+//roWLlyoTZs26fvvv9fYsWOt+W+88Yb+/Oc/a+7cudq8ebOOHz+upUuXWvMzMjL04IMPatiwYdq3b582btyoAQMGlApGAGoIz3w3KgBUzQcffGBCQkJM/fr1TefOnc348ePNv/71L2OMMevXrzfBwcHm3LlzLss0bdrUvPPOO8YYYzp16mQeeuihMtf91VdfGUnm008/tdqOHTtm/Pz8zF//+ldjjDHz5s0zkszXX39t9XnzzTdNZGSkNR0dHW2mTJliTRcWFpprrrnG9OvXzxhjTHp6upFkDh06dBmVAHClcKYHgFcMHDhQP/74o5YvX64777xTGzdu1M0336z58+crPT1dp0+fVlhYmHVWKDAwUAcPHtQ333wjSdq1a5e6d+9e5rr37dsnHx8fdejQwWoLCwtT8+bNtW/fPqvN399fTZs2taajo6OVlZUl6efLaxkZGerUqZM138fHx+VsUrt27dS9e3fFxcXpV7/6ld59913l5OR4pkAAPI7QA8Br6tevr549e+qll17Sli1blJycrAkTJuj8+fOKjo7Wrl27XF779+/Xs88+K0ny8/Mrd72mnMtLxhg5HA5r2tfX12W+w+Go0qWpunXrKjU1VatWrVKrVq00a9YsNW/eXAcPHqz0OgBcOYQeADVGq1atlJeXp5tvvlmZmZny8fHRDTfc4PIKDw+XJLVt21br168vdz1FRUX67LPPrLbs7Gx99dVXatmyZaXG0qBBA0VHR2vbtm1WW1FRkdLT0136ORwOdenSRRMnTtTOnTtVr149l/t+ANQcPLIO4IrLzs7Wr371Kw0bNkxt27ZVUFCQduzYoWnTpqlfv37q0aOHOnXqpP79+2vq1Klq3ry5fvzxR61cuVL9+/dXfHy8JkyYoO7du6tp06YaNGiQioqKtGrVKo0bN07NmjVTv3799Otf/1rvvPOOgoKC9Nxzz+kXv/iF+vXrV+lxPv3005oyZYqaNWumli1bavr06Tpx4oQ1/7PPPtP69euVlJSkiIgIffbZZ/rpp58qHawAXFmEHgBXXGBgoDp06KAZM2bom2++UWFhoRo3bqxf//rXev755+VwOLRy5Uq98MILGjZsmH766SdFRUWpa9euioyMlCQlJibqb3/7m/7nf/5HU6ZMUXBwsLp27WptY968eXr66afVt29fFRQUqGvXrlq5cmWpS1oVeeaZZ5SRkaHk5GTVqVNHw4YN07333quTJ09KkoKDg7Vp0ybNnDlTubm5io2N1RtvvKFevXp5tmAAPMJhqnIBGwAAoJbinh4AAGALhB4AAGALhB4AAGALhB4AAGALhB4AAGALhB4AAGALhB4AAGALhB4AAGALhB4AAGALhB4AAGALhB4AAGALhB4AAGAL/w8q3P83aRFdowAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ax = pending_pods.hist(bins=range(0, 60, 2))\n", + "ax.set_title(\"Dask Worker Pod wait times (First minute)\")\n", + "ax.set_xlabel(\"Seconds\")\n", + "ax.set_ylabel(\"Pods\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we can see clearly that most users get their worker Pods scheduled in less than 5 seconds. " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Cluster scaling and efficiency\n", + "\n", + "Ok so our users are getting clusters nice and quick, that's because there is some warm capacity in the Kubernetes cluster that they are able to grab. When the limit is reached GKE autoscales to add new nodes. When demand drops for a while capacity is released again to save cost. " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets query to see how many nodes there were during the run and combine that with the number of running GPU Pods there were to see how efficiently we were using our resources." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "running_pods = p.query_range(\n", + " 'kube_pod_status_phase{phase=~\"Running|ContainerCreating\",namespace=\"default\"}',\n", + " start_time,\n", + " end_time,\n", + " \"1s\",\n", + ")\n", + "running_pods = running_pods[\n", + " running_pods.columns.drop(list(running_pods.filter(regex=\"prepull\")))\n", + "]\n", + "nodes = p.query_range(\"count(kube_node_info)\", start_time, end_time, \"1s\")\n", + "nodes.columns = [\"Available GPUs\"]\n", + "nodes[\"Available GPUs\"] = (\n", + " nodes[\"Available GPUs\"] * 2\n", + ") # We know our nodes each had 2 GPUs\n", + "nodes[\"Utilized GPUs\"] = running_pods.sum(axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "nodes.plot()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Excellent so we can see our cluster adding and removing nodes as our workload demand changed. The space between the orange and blue lines is our warm capacity. Ideally we want this to be as small as possible. Let's calculate what the gap is.\n", + "\n", + "How many GPU hours did our users utilize?" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15.208055555555555" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gpu_hours_utilized = nodes[\"Utilized GPUs\"].sum() / 60 / 60\n", + "gpu_hours_utilized" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "How many GPU hours were we charged for?" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "23.938333333333333" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gpu_hours_cost = nodes[\"Available GPUs\"].sum() / 60 / 60\n", + "gpu_hours_cost" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What was the overhead?" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'36% overhead'" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "overhead = (1 - (gpu_hours_utilized / gpu_hours_cost)) * 100\n", + "str(int(overhead)) + \"% overhead\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ok not bad, so on our interactive cluster we managed 64% utilization of our GPU resources. Compared to non-autoscaling workloads where users interactively use long running workstations and clusters this is fantastic.\n", + "\n", + "If we measured batch workloads that ran for longer periods we would see this utilization clumb much higher." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Closing thoughts\n", + "\n", + "By sharing a Kubernetes cluster between many users who are all launching many ephemeral Dask Clusters to perform their work we are able to balance cost vs user time. Peaks in individual user demands get smoothed out over time in a multi-tenant model, and the overall peaks and troughs of the day are accomodated by the Kubernetes cluster autoscaler.\n", + "\n", + "We managed to create a responsive experience for our users where they generally got Dask clusters in a few seconds. We also managed to hit 64% utilization of the GPUs in our cluster, a very respectable number for an interactive cluster. \n", + "\n", + "There are more things we could tune to increase utilization, but there are also some tradeoffs to be made here. If we scale down more aggressively then we would end up needing to scale back up more often resulting in more users waiting longer for their clusters. \n", + "\n", + "We can also see there there is some unused capacity between the nodes starting and our workload running. This is the time when image pulling happens, drivers get installed, etc. There are definitely things we could do to improve this so that nodes are ready to go as soon as they have booted.\n", + "\n", + "Compared to every user spinning up dedicated nodes for their individual workloads and paying the driver install and environment pull wait time and overhead cost every time, we are pooling our resources and reusing our capacity effectively." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Teardown\n", + "\n", + "Finally to clean everything up we can delete our GKE cluster by running the following command locally." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Deleting cluster multi-tenant-rapids...done. \n", + "Deleted [https://container.googleapis.com/v1/projects/nv-ai-infra/zones/us-central1/clusters/multi-tenant-rapids].\n" + ] + } + ], + "source": [ + "! gcloud container clusters delete multi-tenant-rapids --region us-central1 --quiet" + ] + } + ], + "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.9.15" + }, + "vscode": { + "interpreter": { + "hash": "f7a54d993f849a0f97fda357a1a3bac7e25a43aff77e618e8d69a4ad36661dba" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/source/examples/rapids-autoscaling-multi-tenant-kubernetes/prometheus-stack-values.yaml b/source/examples/rapids-autoscaling-multi-tenant-kubernetes/prometheus-stack-values.yaml new file mode 100644 index 00000000..561a9548 --- /dev/null +++ b/source/examples/rapids-autoscaling-multi-tenant-kubernetes/prometheus-stack-values.yaml @@ -0,0 +1,7 @@ +# prometheus-stack-values.yaml +serviceMonitorSelectorNilUsesHelmValues: false + +prometheus: + prometheusSpec: + # Setting this to a high frequency so that we have richer data for analysis later + scrapeInterval: 1s diff --git a/source/examples/rapids-autoscaling-multi-tenant-kubernetes/rapids-notebook.yaml b/source/examples/rapids-autoscaling-multi-tenant-kubernetes/rapids-notebook.yaml new file mode 100644 index 00000000..17f03ded --- /dev/null +++ b/source/examples/rapids-autoscaling-multi-tenant-kubernetes/rapids-notebook.yaml @@ -0,0 +1,89 @@ +# rapids-notebook.yaml (extended) +apiVersion: v1 +kind: ServiceAccount +metadata: + name: rapids-dask +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: rapids-dask +rules: + - apiGroups: [""] + resources: ["events"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["pods", "services"] + verbs: ["get", "list", "watch", "create", "delete"] + - apiGroups: [""] + resources: ["pods/log"] + verbs: ["get", "list"] + - apiGroups: [kubernetes.dask.org] + resources: ["*"] + verbs: ["*"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: rapids-dask +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: rapids-dask +subjects: + - kind: ServiceAccount + name: rapids-dask +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: jupyter-server-proxy-config +data: + jupyter_server_config.py: | + c.ServerProxy.host_allowlist = lambda app, host: True +--- +apiVersion: v1 +kind: Service +metadata: + name: rapids-notebook + labels: + app: rapids-notebook +spec: + type: ClusterIP + ports: + - port: 8888 + name: http + targetPort: notebook + selector: + app: rapids-notebook +--- +apiVersion: v1 +kind: Pod +metadata: + name: rapids-notebook + labels: + app: rapids-notebook +spec: + serviceAccountName: rapids-dask + securityContext: + fsGroup: 0 + containers: + - name: rapids-notebook + image: us-central1-docker.pkg.dev/nv-ai-infra/rapidsai/rapidsai-core:22.12-cuda11.5-runtime-ubuntu20.04-py3.9 + resources: + limits: + nvidia.com/gpu: 1 + ports: + - containerPort: 8888 + name: notebook + env: + - name: DASK_DISTRIBUTED__DASHBOARD__LINK + value: "/proxy/{host}:{port}/status" + volumeMounts: + - name: jupyter-server-proxy-config + mountPath: /root/.jupyter/jupyter_server_config.py + subPath: jupyter_server_config.py + volumes: + - name: jupyter-server-proxy-config + configMap: + name: jupyter-server-proxy-config diff --git a/source/examples/rapids-sagemaker-hpo/helper_functions.py b/source/examples/rapids-sagemaker-hpo/helper_functions.py new file mode 100644 index 00000000..27a7a6cd --- /dev/null +++ b/source/examples/rapids-sagemaker-hpo/helper_functions.py @@ -0,0 +1,223 @@ +# +# Copyright (c) 2019-2021, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import os +import random +import traceback +import uuid + +import boto3 + + +def recommend_instance_type(code_choice, dataset_directory): + """ + Based on the code and [airline] dataset-size choices we recommend + instance types that we've tested and are known to work. + Feel free to ignore/make a different choice. + """ + recommended_instance_type = None + + if "CPU" in code_choice and dataset_directory in [ + "1_year", + "3_year", + "NYC_taxi", + ]: # noqa + detail_str = "16 cpu cores, 64GB memory" + recommended_instance_type = "ml.m5.4xlarge" + + elif "CPU" in code_choice and dataset_directory in ["10_year"]: + detail_str = "96 cpu cores, 384GB memory" + recommended_instance_type = "ml.m5.24xlarge" + + if code_choice == "singleGPU": + detail_str = "1x GPU [ V100 ], 16GB GPU memory, 61GB CPU memory" + recommended_instance_type = "ml.p3.2xlarge" + assert dataset_directory not in ["10_year"] # ! switch to multi-GPU + + elif code_choice == "multiGPU": + detail_str = "4x GPUs [ V100 ], 64GB GPU memory, 244GB CPU memory" + recommended_instance_type = "ml.p3.8xlarge" + + print( + f"recommended instance type : {recommended_instance_type} \n" + f"instance details : {detail_str}" + ) + + return recommended_instance_type + + +def validate_dockerfile(rapids_base_container, dockerfile_name="Dockerfile"): + """Validate that our desired rapids base image matches the Dockerfile""" + with open(dockerfile_name) as dockerfile_handle: + if rapids_base_container not in dockerfile_handle.read(): + raise Exception( + "Dockerfile base layer [i.e. FROM statment] does" + " not match the variable rapids_base_container" + ) + + +def summarize_choices( + s3_data_input, + s3_model_output, + code_choice, + algorithm_choice, + cv_folds, + instance_type, + use_spot_instances_flag, + search_strategy, + max_jobs, + max_parallel_jobs, + max_duration_of_experiment_seconds, +): + """ + Print the configuration choices, + often useful before submitting large jobs + """ + print(f"s3 data input =\t{s3_data_input}") + print(f"s3 model output =\t{s3_model_output}") + print(f"compute =\t{code_choice}") + print(f"algorithm =\t{algorithm_choice}, {cv_folds} cv-fold") + print(f"instance =\t{instance_type}") + print(f"spot instances =\t{use_spot_instances_flag}") + print(f"hpo strategy =\t{search_strategy}") + print(f"max_experiments =\t{max_jobs}") + print(f"max_parallel =\t{max_parallel_jobs}") + print(f"max runtime =\t{max_duration_of_experiment_seconds} sec") + + +def summarize_hpo_results(tuning_job_name): + """ + Query tuning results and display the best score, + parameters, and job-name + """ + hpo_results = ( + boto3.Session() + .client("sagemaker") + .describe_hyper_parameter_tuning_job( + HyperParameterTuningJobName=tuning_job_name + ) + ) + + best_job = hpo_results["BestTrainingJob"]["TrainingJobName"] + best_score = hpo_results["BestTrainingJob"][ + "FinalHyperParameterTuningJobObjectiveMetric" + ][ + "Value" + ] # noqa + best_params = hpo_results["BestTrainingJob"]["TunedHyperParameters"] + print(f"best score: {best_score}") + print(f"best params: {best_params}") + print(f"best job-name: {best_job}") + return hpo_results + + +def download_best_model(bucket, s3_model_output, hpo_results, local_directory): + """Download best model from S3""" + try: + target_bucket = boto3.resource("s3").Bucket(bucket) + path_prefix = os.path.join( + s3_model_output.split("/")[-1], + hpo_results["BestTrainingJob"]["TrainingJobName"], + "output", + ) + objects = target_bucket.objects.filter(Prefix=path_prefix) + + for obj in objects: + path, filename = os.path.split(obj.key) + + local_filename = os.path.join(local_directory, "best_" + filename) + s3_path_to_model = os.path.join("s3://", bucket, path_prefix, filename) + target_bucket.download_file(obj.key, local_filename) + print( + f"Successfully downloaded best model\n" + f"> filename: {local_filename}\n" + f"> local directory : {local_directory}\n\n" + f"full S3 path : {s3_path_to_model}" + ) + + return local_filename, s3_path_to_model + + except Exception as download_error: + print(f"! Unable to download best model: {download_error}") + return None + + +def new_job_name_from_config( + dataset_directory, + region, + code_choice, + algorithm_choice, + cv_folds, + instance_type, + trim_limit=32, +): + """ + Build a jobname string that captures the HPO configuration options. + This is helpful for intepreting logs and for general book-keeping + """ + job_name = None + try: + if dataset_directory in ["1_year", "3_year", "10_year"]: + data_choice_str = "air" + validate_region(region) + elif dataset_directory in ["NYC_taxi"]: + data_choice_str = "nyc" + validate_region(region) + else: + data_choice_str = "byo" + + code_choice_str = code_choice[0] + code_choice[-3:] + + if "randomforest" in algorithm_choice.lower(): + algorithm_choice_str = "RF" + if "xgboost" in algorithm_choice.lower(): + algorithm_choice_str = "XGB" + if "kmeans" in algorithm_choice.lower(): + algorithm_choice_str = "KMeans" + + # instance_type_str = '-'.join(instance_type.split('.')[1:]) + + random_str = "".join(random.choices(uuid.uuid4().hex, k=trim_limit)) + + job_name = ( + f"{data_choice_str}-{code_choice_str}" + f"-{algorithm_choice_str}-{cv_folds}cv" + f"-{random_str}" + ) + + job_name = job_name[:trim_limit] + + print(f"generated job name : {job_name}\n") + + except Exception: + traceback.print_exc() + + return job_name + + +def validate_region(region): + """ + Check that the current [compute] region is one of the + two regions where the demo data is hosted + """ + if isinstance(region, list): + region = region[0] + + if region not in ["us-east-1", "us-west-2"]: + raise Exception( + "Unsupported region based on demo data location," + " please switch to us-east-1 or us-west-2" + ) diff --git a/source/platforms/index.md b/source/platforms/index.md index f36eeedf..72a430cf 100644 --- a/source/platforms/index.md +++ b/source/platforms/index.md @@ -39,4 +39,15 @@ Run RAPIDS on Coiled. {bdg}`multi-node` ```` +````{grid-item-card} +:link: databricks +:link-type: doc +Databricks +^^^ +Run RAPIDS on Databricks. + +{bdg}`single-node` +{bdg}`multi-node` +```` + ````` diff --git a/source/platforms/kubernetes.md b/source/platforms/kubernetes.md index 6bcdc818..d0442aa7 100644 --- a/source/platforms/kubernetes.md +++ b/source/platforms/kubernetes.md @@ -37,7 +37,7 @@ spec: fsGroup: 0 containers: - name: rapids-notebook - image: { { rapids_container } } + image: "{{ rapids_container }}" resources: limits: nvidia.com/gpu: 1 diff --git a/source/tools/kubernetes/dask-operator.md b/source/tools/kubernetes/dask-operator.md index f5e574a6..cac31d0d 100644 --- a/source/tools/kubernetes/dask-operator.md +++ b/source/tools/kubernetes/dask-operator.md @@ -304,7 +304,7 @@ to connect a Dask distributed client directly. ```python from dask.distributed import Client -client = Client("rapids-dask-cluster-service:8786") +client = Client("rapids-dask-cluster-scheduler:8786") ``` Alternatively if you are outside of the Kubernetes cluster you can change the `Service` to use [`LoadBalancer`](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) or [`NodePort`](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) or use `kubectl` to port forward the connection locally. @@ -322,10 +322,10 @@ client = Client("localhost:8786") ## Example using `KubeCluster` -In additon to creating clusters via `kubectl` you can also do so from Python with {class}`dask_kubernetes.experimental.KubeCluster`. This class implements the Dask Cluster Manager interface and under the hood creates and manages the `DaskCluster` resource for you. +In additon to creating clusters via `kubectl` you can also do so from Python with {class}`dask_kubernetes.operator.KubeCluster`. This class implements the Dask Cluster Manager interface and under the hood creates and manages the `DaskCluster` resource for you. ```python -from dask_kubernetes.experimental import KubeCluster +from dask_kubernetes.operator import KubeCluster cluster = KubeCluster( name="rapids-dask", diff --git a/source/tools/rapids-docker.md b/source/tools/rapids-docker.md index b248dfbf..a07dee74 100644 --- a/source/tools/rapids-docker.md +++ b/source/tools/rapids-docker.md @@ -1,6 +1,6 @@ -# Docker Images +# Container Images -RAPIDS docker images can be found on [Docker Hub](https://hub.docker.com/r/rapidsai/rapidsai). +Installation instructions for Docker are hosted at the [RAPIDS Container Installation Docs Page](https://docs.rapids.ai/install#docker). ```{relatedexamples}