├── CODEOWNERS
├── LICENSE
├── README.md
├── cifar_utils.py
├── defs.py
├── ex_00_tutorial_overview.ipynb
├── ex_01_remote_funcs.ipynb
├── ex_02_remote_objs.ipynb
├── ex_03_remote_classes.ipynb
├── ex_04_remote_classes_revisited.ipynb
├── ex_05_multiprocess_pool.ipynb
├── ex_06_ray_api_calls.ipynb
├── ex_07_ray_data.ipynb
├── ex_08_ray_air_in_ten_minutes.ipynb
├── ex_09_cifar_ray_air_example.ipynb
├── images
├── California_dataset.png
├── K-means_convergence.gif
├── Ray_AIR.png
├── ai_runtime.jpeg
├── air_ml_workflow.png
├── batch-inference.png
├── batch_predictor.png
├── batch_worker.jpg
├── batchpredict_code.png
├── checkpoints.jpeg
├── cifar-10.png
├── cls_actor_calls.png
├── data_code.png
├── data_highlight.png
├── data_prep.png
├── dataset-arch.png
├── dataset.png
├── dist_multi_pool.png
├── distributed_timeline.png
├── e2e_air.png
├── fashion-mnist-sprite.jpeg
├── gpu_saturation.png
├── hpo-neural-network-example.png
├── map_reduce.png
├── object_resolution.png
├── object_store.png
├── online_predictor.png
├── pipeline_window.jpg
├── py_2_ray.png
├── ray-air.svg
├── ray-logo.png
├── ray_air_pipeline.png
├── ray_arch.png
├── ray_basic_patterns.png
├── ray_dataset_pipeline.jpg
├── ray_logo.png
├── ray_task.png
├── ray_tune_report_launch_trainables.png
├── ray_tune_report_metrics.png
├── ray_worker_actor_1.png
├── ray_worker_actor_2.png
├── same_data_different_model.png
├── sequential_timeline.png
├── serve_code.png
├── serve_highlight.png
├── shared_memory.png
├── shared_memory_plasma_store.png
├── task_api_add_array.png
├── task_dependencies_graphs.png
├── train_code.png
├── train_highlight.png
├── trainer.png
├── trainer_worker.jpg
├── tune_code.png
├── tune_highlight.png
├── tuner.png
├── what-are-hyperparameters.png
└── x_y_training_data.png
├── model_helper_utils.py
├── requirements.txt
├── retired
├── README.md
├── data
│ ├── file_1.txt
│ └── file_2.txt
├── ex_00_ray_tutorial_overview.ipynb
├── ex_01_remote_funcs.ipynb
├── ex_02_remote_objs.ipynb
├── ex_03_remote_classes.ipynb
├── ex_04_exploring_ray_api_calls.ipynb
├── ex_05_running_ray_clusters.ipynb
├── ex_06_xbgboost_train_tune.ipynb
├── ex_07_ray_tune_scklearn.ipynb
├── ex_08_model_serving_challenges.ipynb
├── ex_08_ray_air_in_ten_minutes.ipynb
├── ex_09_ray_serve_create_and_access_deployments.ipynb
├── ex_10_ray_serve_example.ipynb
├── ex_11_ray_serve_sentiment_tweets.ipynb
├── extra
│ ├── ex_08_Understanding-Hyperparameter-Tuning.ipynb
│ ├── ex_09_ray_train.ipynb
│ ├── mp_all_nb.ipynb
│ ├── ray_air_hugging_face.ipynb
│ └── ray_data_nyc.ipynb
├── highly_parallel.ipynb
├── images
│ ├── PatternsMLProduction.png
│ ├── PyCon2022_Logo.png
│ ├── actor_and_workders.png
│ ├── architecture.png
│ ├── func_class_deployment.png
│ ├── func_class_deployment_2.png
│ ├── object_resolution.png
│ ├── ray-logo.png
│ ├── ray_basic_patterns.png
│ ├── ray_cluster.png
│ ├── ray_serve_deployment_workflow.png
│ ├── ray_serve_overview.png
│ ├── ray_tune_dist_hpo.png
│ ├── ray_worker_actor_1.png
│ ├── ray_worker_actor_2.png
│ ├── sentiment_analysis.jpeg
│ ├── shared_memory.png
│ ├── shared_memory_plasma_store.png
│ ├── task_api_add_array.png
│ ├── task_dependencies_graphs.png
│ ├── task_ownership.png
│ └── tune_flow.png
├── requirements.txt
├── slides
│ ├── pyconus2022
│ │ └── pyconsus_slides.pdf
│ └── weekly-demos
│ │ └── presentation_slides.pdf
├── solutions
│ ├── ex_01_solution.ipynb
│ ├── ex_02_solution.ipynb
│ ├── ex_03_solution.ipynb
│ ├── ex_08_solution.ipynb
│ └── ex_10_solution.ipynb
└── submit.py
├── slides
├── pydata_nyc
│ └── ray-core-tutorial-slides.pdf
├── pydata_seattle
│ └── ray-core-tutorial-slides.pdf
└── ucsd
│ └── ucsd_lecture.pdf
├── solutions
├── ex_01_solution.ipynb
├── ex_02_solution.ipynb
├── ex_03_solution.ipynb
├── ex_04_solution.ipynb
├── ex_05_solution.ipynb
└── ex_07_solutions.ipynb
└── tasks_helper_utils.py
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @dmatrix
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Introduction to Ray for Distributed Applications
2 |
3 | © 2019-2024, Anyscale. All Rights Reserved
4 |
5 |
6 |
7 | An introduction to [Ray](https://www.ray.io/), the system for scaling your Python and machine learning workloads from a laptop to a cluster. We'll start with a hands-on exploration of the core Ray APIs for distributed workloads, covering basic distributed Ray Core API patterns, and
8 | then move on to a quick introduction to one of Ray's native libraries:
9 |
10 | * Remote functions as tasks
11 | * Remote objects as futures
12 | * Remote classes as stateful actors
13 | * Quick introduction to Ray's data and Ray libraries
14 |
15 | ### Outline for this Tutorial Lesson 📖
16 |
17 | Divided into three modules, each module will take about an hour, combined with lecture and followed by hands-on 👩💻 exercises in class.
18 |
19 | ### Module 1
20 | * Lecture 20 mins
21 | * What is Ray and Why & Origins
22 | * Ray Component & Architecture
23 | * Ray Core API Decorators & Patterns
24 | * Notebooks & Exercises
25 | * Ray Functions as distribtued stateless tasks
26 | * Ray Objects as Distributed future objects
27 | * Ray Actors as distributed stateful services
28 |
29 | ### Module 2
30 | * Ray Actors Revisited: Understand a common pattern used in Ray native libraries
31 | * Tour of the Ray APIs: a quick look at common APIs and some tricks & tips if new to Ray
32 | * Distributed multiprocessing.Pool: different strategies to scale Python with Ray
33 | * Notebooks & Exercises
34 |
35 | ### Module 3
36 | * Brief Introduction to Ray Data: A gentle introduction to Ray Datasets
37 | * Brief Introduction to Ray AIR: A gentle introduction to Ray AIR
38 |
39 | ### Extra Modules
40 | * Additional and supplemental material to peruse at leisure time.
41 |
42 | ### In this tutorial, you will:
43 | * 👩💻Understand what the Ray ecosystem is and why to use it
44 | * 📖Learn Ray's Core basic APIs and Python APIs
45 | * 🧑💻Use Ray APIs to convert Python functions and classes into distributed stateless and stateful tasks
46 | * 🎛 Use Dashboard for inspection and observation
47 | * 🧑💻Discover the purpose of Ray native libraries and how to use them
48 |
49 | ### 🎓Prerequisite knowledge ###
50 | **Level**: Beginners or new to Ray
51 |
52 | * Familiarity with Python 3.9+ and basic programming concepts: lists, comprehensions, decorators, functions, dictionaries, classes, loops, exceptional handling, etc
53 | * Laptop with at least 8-16GB Memory with latest Chrome browser
54 | * Prior knowledge of Jupyter notebooks
55 | * Basic knowledge of machine learning concepts
56 |
57 |
58 | ## 👩 Setup instructions for local laptop 💻
59 | If you want to follow the material in class, please follow this instructions before class to setup your laptop.
60 |
61 | ### Using conda
62 | If you need to install Anaconda, follow the instructions [here](https://www.anaconda.com/products/distribution).
63 | If you already have Anaconda installed, consider running conda `upgrade --all.`
64 |
65 | 1. `conda create -n ray-core-tutorial python=3.10`
66 | 2. `conda activate ray-core-tutorial`
67 | 3. `git clone git@github.com:dmatrix/ray-core-tutorial.git`
68 | 4. `cd to `
69 | 5. `python3 -m pip install -r requirements.txt`
70 | 7. `jupyter lab`
71 |
72 | ### Installing on Apple M1
73 | If you are using [Apple M1](https://docs.ray.io/en/latest/ray-overview/installation.html#m1-mac-apple-silicon-support) laptop 🍎 follow the following instructions:
74 |
75 | 1. `conda create -n ray-core-tutorial python=3.10`
76 | 2. `conda activate ray-core-tutorial`
77 | 3. `conda install grpcio=1.43.0 -c conda-forge`
78 | 4. `git clone git@github.com:dmatrix/ray-core-tutorial.git`
79 | 5. `cd to `
80 | 6. `python3 -m pip install -r requirements.txt`
81 | 9. `jupyter lab`
82 |
83 | ### Using only pip
84 | 1. `git clone git@github.com:anyscale/ray-summit-2022-training.git`
85 | 2. `cd to `
86 | 3. `python3 -m pip install -r requirements.txt`
87 | 5. `jupyter lab`
88 |
89 | Let's have 😜 fun with Ray!
90 |
91 | To start tutorials, [go here](ex_00_tutorial_overview.ipynb).
92 |
93 | And when you are finished, help us improve training. Please fill out this [survey](https://bit.ly/pydata-nyc-2022)
94 |
--------------------------------------------------------------------------------
/cifar_utils.py:
--------------------------------------------------------------------------------
1 |
2 | from typing import Dict, Tuple
3 |
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 | import pandas as pd
7 | import tqdm
8 |
9 | import torch
10 | import torch.nn as nn
11 | import torch.optim as optim
12 | import torch.nn.functional as F
13 | import torchvision
14 | import torchvision.transforms as transforms
15 |
16 | from ray import train
17 | import ray.train.torch
18 | from ray.data.extensions import TensorArray
19 | from ray.air import session
20 | from ray.train.torch import TorchCheckpoint
21 | from ray.serve.http_adapters import NdArray
22 |
23 | CLASSES = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
24 |
25 | transform = transforms.Compose(
26 | # this is the reason for normalizing (with mean, std) for each RGB channel
27 | # Normalization helps reduce or skewing and helps with faster CNN training
28 | # https://discuss.pytorch.org/t/understanding-transform-normalize/21730
29 | [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]
30 | )
31 |
32 | def train_dataset_factory():
33 | """
34 | Download the train CiFAR 10 dataset into the root dir
35 | """
36 | return torchvision.datasets.CIFAR10(root="~/data",
37 | download=True,
38 | train=True,
39 | transform=transform)
40 |
41 | def test_dataset_factory():
42 | """
43 | Download the test CiFAR 10 dataset into the root dir
44 | """
45 | return torchvision.datasets.CIFAR10(root="~/data",
46 | download=True,
47 | train=False,
48 | transform=transform)
49 |
50 | def convert_batch_to_numpy(batch: Tuple[torch.Tensor, int]) -> Dict[str, np.ndarray]:
51 | images = np.array([image.numpy() for image, _ in batch])
52 | labels = np.array([label for _, label in batch])
53 | return {"image": images, "label": labels}
54 |
55 | class BasicBlock(nn.Module):
56 | expansion = 1
57 |
58 |
59 | def __init__(self, in_planes, planes, stride=1):
60 | super(BasicBlock, self).__init__()
61 |
62 | DROPOUT = 0.1
63 |
64 | self.conv1 = nn.Conv2d(
65 | in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
66 | self.bn1 = nn.BatchNorm2d(planes)
67 | self.dropout = nn.Dropout(DROPOUT)
68 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,
69 | stride=1, padding=1, bias=False)
70 | self.bn2 = nn.BatchNorm2d(planes)
71 | self.dropout = nn.Dropout(DROPOUT)
72 |
73 | self.shortcut = nn.Sequential()
74 | if stride != 1 or in_planes != self.expansion*planes:
75 | self.shortcut = nn.Sequential(
76 | nn.Conv2d(in_planes, self.expansion*planes,
77 | kernel_size=1, stride=stride, bias=False),
78 | nn.BatchNorm2d(self.expansion*planes),
79 | nn.Dropout(DROPOUT)
80 | )
81 |
82 | def forward(self, x):
83 | out = F.relu(self.dropout(self.bn1(self.conv1(x))))
84 | out = self.dropout(self.bn2(self.conv2(out)))
85 | out += self.shortcut(x)
86 | out = F.relu(out)
87 | return out
88 |
89 |
90 | class ResNet(nn.Module):
91 | def __init__(self, block, num_blocks, num_classes=10):
92 | super(ResNet, self).__init__()
93 | self.in_planes = 64
94 |
95 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3,
96 | stride=1, padding=1, bias=False)
97 | self.bn1 = nn.BatchNorm2d(64)
98 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
99 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
100 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
101 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
102 | self.linear = nn.Linear(512*block.expansion, num_classes)
103 |
104 | def _make_layer(self, block, planes, num_blocks, stride):
105 | strides = [stride] + [1]*(num_blocks-1)
106 | layers = []
107 | for stride in strides:
108 | layers.append(block(self.in_planes, planes, stride))
109 | self.in_planes = planes * block.expansion
110 | return nn.Sequential(*layers)
111 |
112 | def forward(self, x):
113 | out = F.relu(self.bn1(self.conv1(x)))
114 | out = self.layer1(out)
115 | out = self.layer2(out)
116 | out = self.layer3(out)
117 | out = self.layer4(out)
118 | out = F.avg_pool2d(out, 4)
119 | out = out.view(out.size(0), -1)
120 | out = self.linear(out)
121 | return F.log_softmax(out, dim=-1)
122 |
123 |
124 | def ResNet18():
125 | return ResNet(BasicBlock, [2, 2, 2, 2])
126 |
127 |
128 | def train_loop_per_worker(config):
129 | device = (ray.train.torch.get_device() if torch.cuda.is_available() else torch.device("cpu")
130 | )
131 |
132 | # Prepare model for training. This involves moving the
133 | # model to appropriate device, putting into the training mode
134 | model = train.torch.prepare_model(ResNet18())
135 |
136 | # Define loss function and optimizer
137 | criterion = nn.CrossEntropyLoss()
138 | optimizer = optim.SGD(model.parameters(), lr=config["lr"], momentum=0.9)
139 |
140 | # Fetch training Ray dataset from the session; this is automatically
141 | # distributed to the right worker node's process where the training
142 | # run
143 | train_dataset_shard = session.get_dataset_shard("train")
144 |
145 | # Iterate over epochs
146 | epochs = config.get("epochs", 10)
147 | batch_size = config.get("batch_size", 32)
148 | verbose = config.get("verbose", 0)
149 | lr = config.get("lr", 0.01)
150 |
151 |
152 | for epoch in tqdm.tqdm(range(epochs)):
153 | if verbose:
154 | print(f"Training epoch:{epoch+1}/{epochs} | batch_size:{batch_size} | lr:{lr}")
155 |
156 | train_loss = 0.0
157 | train_loss = 0.0
158 | total_images = 0
159 |
160 | # loop over batches for each epoch
161 | train_dataset_batches = train_dataset_shard.iter_torch_batches(
162 | batch_size=batch_size,
163 | )
164 | for i, batch in enumerate(train_dataset_batches):
165 | # Get the inputs and labels
166 | inputs, labels = batch["image"], batch["label"]
167 | num_images = inputs.shape[0]
168 | inputs, labels = inputs.to(device), labels.to(device)
169 |
170 | # zero the parameter gradients
171 | optimizer.zero_grad()
172 |
173 | # forward + backward + optimize
174 | outputs = model(inputs)
175 | loss = criterion(outputs, labels)
176 | loss.backward()
177 | optimizer.step()
178 |
179 | train_loss += loss.item() * num_images
180 | total_images += num_images
181 |
182 | train_loss /= total_images
183 | metrics = dict(train_loss=train_loss)
184 | if verbose:
185 | print(f"training loss: {train_loss:.3f} | epoch: {epoch+1}/{epochs} | batch: {i+1}")
186 |
187 | # Create a Torch checkpoint from the models state dictionary after each
188 | # epoch and report the metrics
189 | checkpoint = TorchCheckpoint.from_state_dict(model.module.state_dict())
190 | session.report(metrics, checkpoint=checkpoint)
191 |
192 | def convert_logits_to_classes(df):
193 | best_class = df["predictions"].map(lambda x: x.argmax())
194 | df["prediction"] = best_class
195 | return df
196 |
197 | def calculate_prediction_scores(df):
198 | df["correct"] = df["prediction"] == df["label"]
199 | return df[["prediction", "label", "correct"]]
200 |
201 | def json_to_numpy(payload: NdArray) -> pd.DataFrame:
202 | """Accepts an NdArray JSON from an HTTP body and converts it to a Numpy Array."""
203 | # Have to explicitly convert to float since np.array reads as a double.
204 | arr = np.array(payload.array, dtype=np.float32)
205 | return arr
206 |
207 | def to_prediction_cls(lst):
208 | max_value = max(lst)
209 | idx = lst.index(max_value)
210 | cls = CLASSES[idx]
211 | return idx,cls
212 |
213 | def img_show(img):
214 | img = img / 2 + 0.5 # unnormalize
215 | # npimg = img.numpy()
216 | plt.imshow(np.transpose(img, (1, 2, 0)))
217 | plt.show()
--------------------------------------------------------------------------------
/defs.py:
--------------------------------------------------------------------------------
1 | import multiprocessing as mp
2 | import numpy as np
3 | import scipy.signal
4 |
5 |
6 | def get_cpu_count():
7 | return mp.cpu_count()
8 |
9 |
10 | def is_prime(n):
11 | for divisor in range(2, int(n ** 0.5) + 1):
12 | if n % divisor == 0:
13 | return 0
14 | return 1
15 |
16 | def inefficient_fib(n=None):
17 | """Compute intensive calculation for the nth fibonacci number"""
18 | if n <= 1:
19 | return n
20 | return inefficient_fib(n - 1) + inefficient_fib(n - 2)
21 |
22 | iterations_count = iterations_count = round(1e4)
23 | def complex_operation_numpy(index):
24 | data = np.ones(iterations_count)
25 | val = np.exp(data) * np.sinh(data)
26 | return val.sum()
27 |
28 | def f_ray_image_signal(args):
29 | image, random_filter = args
30 | # Do some image processing: convolve two 2-dimensional arrays.
31 | return scipy.signal.convolve2d(image, random_filter)[::5, ::5]
32 |
33 | def f_py_image_signal(args):
34 | image, random_filter = args
35 | # Do some image processing: convolve two 2-dimensional arrays.
36 | return scipy.signal.convolve2d(image, random_filter)[::5, ::5]
37 |
38 |
--------------------------------------------------------------------------------
/ex_00_tutorial_overview.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Ray Tutorial Basic Core APIs - Overview\n",
8 | "\n",
9 | "© 2021-2022, Anyscale. All Rights Reserved\n",
10 | "\n",
11 | "
\n",
12 | "\n",
13 | "## About This Tutorial\n",
14 | "\n",
15 | "\n",
16 | "See the instructions in the [README](README.md) tutorial overview to set up your environment to use this tutorial if you want to run this on your laptop. If you using Anyscale hosted enviroment for this class, then you don't have to do anything. "
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "metadata": {},
22 | "source": [
23 | "| | Lesson | Description |\n",
24 | "| :-- | :----- | :---------- |\n",
25 | "| | **Module 1** | **Ray Tasks, Ray Objects, and Ray Actors** |\n",
26 | "| | Table of contents | Overview of this tutorial. |\n",
27 | "| 01 | [Ray Remote Functions ](ex_01_remote_funcs.ipynb) |The remote function as stateless tasks pattern. |\n",
28 | "| 02 | [Ray Remote Objects](ex_02_remote_objs.ipynb) |The remote objects, stored in a immutable distributed store, as futures pattern. |\n",
29 | "| 03 | [Ray Remote Classes](ex_03_remote_classes.ipynb)| The remote class as a distributed and scalable stateful service pattern.|\n",
30 | "| | **Module 2** | **Focus on Ray Actor Tree Patterns, Ray Multiprocess Pool for clusters, Ray API Tour** |\n",
31 | "| 04 | [Ray Remote Classes Revisited](ex_04_remote_classes_revisited.ipynb) |The stateful tree Actor pattern: Understand a common pattern used in Ray native libraries to scale workloads |\n",
32 | "| 05 | [Ray Multiprocess Pool for clusters](ex_05_multiprocess_pool.ipynb) | Ray's multiprocess pool for clusters: examine different strategies to scale Python with Ray|\n",
33 | "| 06 | [Ray API Calls Tour](ex_06_ray_api_calls.ipynb) |A look at common Ray API calls and some tricks & tips if new to Ray |\n",
34 | "| | **Module 3** | **Brief introduction Ray Data** |\n",
35 | "| 07 | [Introduction to Ray Data](ex_07_ray_data.ipynb) | A gentle introduction to Ray Datasets 10 minutes|\n",
36 | "| 08 | [Introduction to Ray AIR](ex_08_ray_air_in_ten_minutes.ipynb) | A gentle introduction to Ray AIR in 10 minutes |\n",
37 | "| 09 | [CiFAR-10 Classification](ex_09_cifar_ray_air_example.ipynb) | An end to end ML example using Ray AIR|\n"
38 | ]
39 | }
40 | ],
41 | "metadata": {
42 | "kernelspec": {
43 | "display_name": "Python 3 (ipykernel)",
44 | "language": "python",
45 | "name": "python3"
46 | },
47 | "language_info": {
48 | "codemirror_mode": {
49 | "name": "ipython",
50 | "version": 3
51 | },
52 | "file_extension": ".py",
53 | "mimetype": "text/x-python",
54 | "name": "python",
55 | "nbconvert_exporter": "python",
56 | "pygments_lexer": "ipython3",
57 | "version": "3.8.13"
58 | }
59 | },
60 | "nbformat": 4,
61 | "nbformat_minor": 4
62 | }
63 |
--------------------------------------------------------------------------------
/images/California_dataset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/California_dataset.png
--------------------------------------------------------------------------------
/images/K-means_convergence.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/K-means_convergence.gif
--------------------------------------------------------------------------------
/images/Ray_AIR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/Ray_AIR.png
--------------------------------------------------------------------------------
/images/ai_runtime.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ai_runtime.jpeg
--------------------------------------------------------------------------------
/images/air_ml_workflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/air_ml_workflow.png
--------------------------------------------------------------------------------
/images/batch-inference.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/batch-inference.png
--------------------------------------------------------------------------------
/images/batch_predictor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/batch_predictor.png
--------------------------------------------------------------------------------
/images/batch_worker.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/batch_worker.jpg
--------------------------------------------------------------------------------
/images/batchpredict_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/batchpredict_code.png
--------------------------------------------------------------------------------
/images/checkpoints.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/checkpoints.jpeg
--------------------------------------------------------------------------------
/images/cifar-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/cifar-10.png
--------------------------------------------------------------------------------
/images/cls_actor_calls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/cls_actor_calls.png
--------------------------------------------------------------------------------
/images/data_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/data_code.png
--------------------------------------------------------------------------------
/images/data_highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/data_highlight.png
--------------------------------------------------------------------------------
/images/data_prep.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/data_prep.png
--------------------------------------------------------------------------------
/images/dataset-arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/dataset-arch.png
--------------------------------------------------------------------------------
/images/dataset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/dataset.png
--------------------------------------------------------------------------------
/images/dist_multi_pool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/dist_multi_pool.png
--------------------------------------------------------------------------------
/images/distributed_timeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/distributed_timeline.png
--------------------------------------------------------------------------------
/images/e2e_air.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/e2e_air.png
--------------------------------------------------------------------------------
/images/fashion-mnist-sprite.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/fashion-mnist-sprite.jpeg
--------------------------------------------------------------------------------
/images/gpu_saturation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/gpu_saturation.png
--------------------------------------------------------------------------------
/images/hpo-neural-network-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/hpo-neural-network-example.png
--------------------------------------------------------------------------------
/images/map_reduce.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/map_reduce.png
--------------------------------------------------------------------------------
/images/object_resolution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/object_resolution.png
--------------------------------------------------------------------------------
/images/object_store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/object_store.png
--------------------------------------------------------------------------------
/images/online_predictor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/online_predictor.png
--------------------------------------------------------------------------------
/images/pipeline_window.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/pipeline_window.jpg
--------------------------------------------------------------------------------
/images/py_2_ray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/py_2_ray.png
--------------------------------------------------------------------------------
/images/ray-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray-logo.png
--------------------------------------------------------------------------------
/images/ray_air_pipeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_air_pipeline.png
--------------------------------------------------------------------------------
/images/ray_arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_arch.png
--------------------------------------------------------------------------------
/images/ray_basic_patterns.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_basic_patterns.png
--------------------------------------------------------------------------------
/images/ray_dataset_pipeline.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_dataset_pipeline.jpg
--------------------------------------------------------------------------------
/images/ray_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_logo.png
--------------------------------------------------------------------------------
/images/ray_task.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_task.png
--------------------------------------------------------------------------------
/images/ray_tune_report_launch_trainables.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_tune_report_launch_trainables.png
--------------------------------------------------------------------------------
/images/ray_tune_report_metrics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_tune_report_metrics.png
--------------------------------------------------------------------------------
/images/ray_worker_actor_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_worker_actor_1.png
--------------------------------------------------------------------------------
/images/ray_worker_actor_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/ray_worker_actor_2.png
--------------------------------------------------------------------------------
/images/same_data_different_model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/same_data_different_model.png
--------------------------------------------------------------------------------
/images/sequential_timeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/sequential_timeline.png
--------------------------------------------------------------------------------
/images/serve_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/serve_code.png
--------------------------------------------------------------------------------
/images/serve_highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/serve_highlight.png
--------------------------------------------------------------------------------
/images/shared_memory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/shared_memory.png
--------------------------------------------------------------------------------
/images/shared_memory_plasma_store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/shared_memory_plasma_store.png
--------------------------------------------------------------------------------
/images/task_api_add_array.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/task_api_add_array.png
--------------------------------------------------------------------------------
/images/task_dependencies_graphs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/task_dependencies_graphs.png
--------------------------------------------------------------------------------
/images/train_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/train_code.png
--------------------------------------------------------------------------------
/images/train_highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/train_highlight.png
--------------------------------------------------------------------------------
/images/trainer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/trainer.png
--------------------------------------------------------------------------------
/images/trainer_worker.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/trainer_worker.jpg
--------------------------------------------------------------------------------
/images/tune_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/tune_code.png
--------------------------------------------------------------------------------
/images/tune_highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/tune_highlight.png
--------------------------------------------------------------------------------
/images/tuner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/tuner.png
--------------------------------------------------------------------------------
/images/what-are-hyperparameters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/what-are-hyperparameters.png
--------------------------------------------------------------------------------
/images/x_y_training_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/images/x_y_training_data.png
--------------------------------------------------------------------------------
/model_helper_utils.py:
--------------------------------------------------------------------------------
1 | import time
2 | from typing import Tuple, Dict, Any
3 | from sklearn.datasets import fetch_california_housing
4 | from sklearn.ensemble import RandomForestRegressor
5 | from sklearn.tree import DecisionTreeRegressor
6 | from sklearn.metrics import mean_squared_error
7 | from sklearn.model_selection import train_test_split
8 | import xgboost as xgb
9 | import ray
10 |
11 | # states to inspect
12 | STATES = ["INITIALIZED", "RUNNING", "DONE"]
13 |
14 | DECISION_TREE_CONFIGS = {"max_depth": 15,
15 | "name": "decision_tree"}
16 |
17 | RANDOM_FOREST_CONFIGS = {"n_estimators": 150,
18 | "name": "random_forest"}
19 |
20 | XGBOOST_CONFIGS = {"max_depth": 10,
21 | "n_estimators": 150,
22 | "lr": 0.1,
23 | "eta": 0.3,
24 | "colsample_bytree": 1,
25 | "name": "xgboost"}
26 |
27 | class ActorCls:
28 | """
29 | Base class for our Ray Actor workers models
30 | """
31 | def __init__(self, configs: Dict[Any, Any]) -> None:
32 | self.configs = configs
33 | self.name = configs["name"]
34 | self.state = STATES[0]
35 | self.X, self.y = None, None
36 | self.X_train, self.X_test = None, None
37 | self.y_train, self.y_test = None, None
38 | self.model = None
39 |
40 | def get_name(self) -> str:
41 | return self.name
42 |
43 | def get_state(self) -> str:
44 | return self.state
45 |
46 |
47 | def _prepare_data_and_model(self) -> None:
48 | self.X, self.y = fetch_california_housing(return_X_y=True, as_frame=True)
49 | self.X_train, self.X_test, self.y_train, self.y_test = train_test_split(self.X, self.y, test_size=0.2, random_state=4)
50 |
51 | def train_and_evaluate_model(self) -> Dict[Any, Any]:
52 | """
53 | Overwrite this function in super class
54 | """
55 | pass
56 |
57 |
58 | @ray.remote
59 | class RFRActor(ActorCls):
60 | """
61 | An actor model to train and score the calfornia house data using Random Forest Regressor
62 | """
63 | def __init__(self, configs):
64 | super().__init__(configs)
65 | self.estimators = configs["n_estimators"]
66 |
67 |
68 | def train_and_evaluate_model(self) -> Dict[Any, Any]:
69 | """
70 | Train the model and evaluate and report MSE
71 | """
72 |
73 | self._prepare_data_and_model()
74 | self.model = RandomForestRegressor(n_estimators=self.estimators, random_state=42)
75 |
76 | print(f"Start training model {self.name} with estimators: {self.estimators} ...")
77 |
78 | start_time = time.time()
79 | self.model.fit(self.X_train, self.y_train)
80 | self.state = STATES[1]
81 | y_pred = self.model.predict(self.X_test)
82 | score = mean_squared_error(self.y_test, y_pred)
83 | self.state = STATES[2]
84 |
85 | end_time = time.time()
86 | print(f"End training model {self.name} with estimators: {self.estimators} took: {end_time - start_time:.2f} seconds")
87 |
88 | return { "state": self.get_state(),
89 | "name": self.get_name(),
90 | "estimators": self.estimators,
91 | "mse": round(score, 4),
92 | "time": round(end_time - start_time, 2)}
93 |
94 |
95 | @ray.remote
96 | class DTActor(ActorCls):
97 | """
98 | An actor model to train and score the calfornia house data using Decision Tree Regressor
99 | """
100 | def __init__(self, configs):
101 |
102 | super().__init__(configs)
103 | self.max_depth = configs["max_depth"]
104 |
105 | def train_and_evaluate_model(self) -> Dict[Any, Any]:
106 | """
107 | Train the model and evaluate and report MSE
108 | """
109 |
110 | self._prepare_data_and_model()
111 | self.model = DecisionTreeRegressor(max_depth=self.max_depth, random_state=42)
112 |
113 | print(f"Start training model {self.name} with max depth: { self.max_depth } ...")
114 |
115 | start_time = time.time()
116 | self.model.fit(self.X_train, self.y_train)
117 | self.state = STATES[1]
118 | y_pred = self.model.predict(self.X_test)
119 | score = mean_squared_error(self.y_test, y_pred)
120 | self.state = STATES[2]
121 |
122 | end_time = time.time()
123 | print(f"End training model {self.name} with max_depth tree: {self.max_depth} took: {end_time - start_time:.2f} seconds")
124 |
125 | return { "state": self.get_state(),
126 | "name": self.get_name(),
127 | "max_depth": self.max_depth,
128 | "mse": round(score, 4),
129 | "time": round(end_time - start_time, 2)}
130 |
131 | @ray.remote
132 | class XGBoostActor(ActorCls):
133 | """
134 | An actor model to train and score the calfornia house data using XGBoost Regressor
135 | """
136 | def __init__(self, configs):
137 |
138 | super().__init__(configs)
139 |
140 | self.max_depth = configs["max_depth"]
141 | self.estimators = configs["n_estimators"]
142 | self.colsample = configs["colsample_bytree"]
143 | self.eta = configs["eta"]
144 | self.lr = configs["lr"]
145 |
146 | def train_and_evaluate_model(self) -> Dict[Any, Any]:
147 | """
148 | Train the model and evaluate and report MSE
149 | """
150 |
151 | self._prepare_data_and_model()
152 | self.model = xgb.XGBRegressor(objective='reg:squarederror',
153 | colsample_bytree=self.colsample,
154 | eta=self.eta,
155 | learning_rate = self.lr,
156 | max_depth=self.max_depth,
157 | n_estimators=self.estimators,
158 | random_state=42)
159 |
160 | print(f"Start training model {self.name} with estimators: {self.estimators} and max depth: { self.max_depth } ...")
161 | start_time = time.time()
162 | self.model.fit(self.X_train, self.y_train)
163 | self.state = STATES[1]
164 | y_pred = self.model.predict(self.X_test)
165 | score = mean_squared_error(self.y_test, y_pred)
166 | self.state = STATES[2]
167 |
168 | end_time = time.time()
169 | print(f"End training model {self.name} with estimators: {self.estimators} and max depth: { self.max_depth } and took: {end_time - start_time:.2f}")
170 |
171 | return {"state": self.get_state(),
172 | "name": self.get_name(),
173 | "max_depth": self.max_depth,
174 | "mse": round(score, 4),
175 | "estimators": self.estimators,
176 | "time": round(end_time - start_time, 2)}
177 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | ray[default]
2 | ray[all]
3 | jupyter
4 | jupyterlab
5 | scikit-learn
6 | tune-sklearn
7 | xgboost
8 | xgboost-ray
9 | tqdm
10 | torch
11 | torchvision
12 | scipy
13 | torchinfo
14 | matplotlib
15 |
--------------------------------------------------------------------------------
/retired/README.md:
--------------------------------------------------------------------------------
1 | # Introduction to Ray Ecosystem for Distributed Applications
2 |
3 |
4 |
5 | Welcome to the tutorial at PyCon US 2022 in Salt Lake City
6 |
7 |
8 |
9 |
10 | This is a gentle introduction to basic Ray programming patterns and APIs for distributing computing. In this tutorial, we will cover at least three basic Ray patterns and its respective Ray Core APIs.
11 |
12 | * Remote Stateless Ray Tasks
13 | * Remote Stateful Ray Actors
14 | * Remote ObectRefs as Futures
15 |
16 | Additionally, a brief introductino to two of the Ray native libraries:
17 | * Introduction to Ray Tune and Ray Serve
18 |
19 | By no means all the Ray patterns and APIs are covered here. We recommend that you follow the references for [advanced patterns and antipatterns](https://docs.ray.io/en/latest/ray-design-patterns/index.html) if you want to use Ray to write your own ML-based libraries or want to take existing Python single-process or single-node multi-core applications and covert them into distributed multi-core, multi-node processes on a Ray cluster.
20 |
21 | Knowing these Ray patterns and anti-patterns will guide you in writing effective and robust distributed applications using the Ray framework and its recommended usage of Ray APIs.
22 |
23 | Additoinaly, we'll briefly examine how to use Tune APIs to train 🚆 and tune 🎸 your model 🤖, followed by an introduction
24 | to Ray Serve for deploying and serving models.
25 |
26 | ### 🧑🎓Prerequisite knowledge ###
27 |
28 | Some prior experience with Python and Jupyter notebooks will be helpful, but we'll explain most details as we go if you haven't used notebooks before. Knowledge of basic machine learning concepts, including hyperparameters, model serving, and principles of distributed computing is helpful,
29 | but not required.
30 |
31 | All exercises can be done on your laptop 💻, preferably running a Linux or macOS 🍎, using all its cores. Because you won’t have access to Ray clusters, we have to run Ray locally and parallelize all your tasks on all your cores.
32 |
33 | Python 3.7+ is required on your laptop, and some minimal installation of quick python packages using conda and pip.
34 |
35 | ### 👩🏫 Instructions to get started
36 |
37 | We assume that you have a `conda` installed.
38 |
39 | 1. `conda create -n ray-core-tutorial python=3.8`
40 | 2. `conda activate ray-core-tutorial`
41 | 3. `git clone git@github.com:dmatrix/ray-core-tutorial.git`
42 | 4. `cd` to
43 | 5. `python3 -m pip install -r requirements.txt`
44 | 6. `python3 -m ipykernel install`
45 | 7. `jupyter lab`
46 |
47 | If you are using **Apple M1 laptop** 🍎 follow the following instructions:
48 |
49 | 1. `conda create -n ray-core-tutorial python=3.8`
50 | 2. `conda activate ray-core-tutorial`
51 | 3. `conda install grpcio`
52 | 4. `python3 -m pip install -r requirements.txt`
53 | 5. `python3 -m ipykernel install`
54 | 6. `conda install jupyterlab`
55 | 7. `jupyter lab`
56 |
57 | Let's have 😜 fun with Ray @ PyCon US 2022!
58 |
59 | Thank you 🙏,
60 |
61 | Jules
62 |
--------------------------------------------------------------------------------
/retired/data/file_1.txt:
--------------------------------------------------------------------------------
1 | 0, 48, 72, 75, 54, 89, 84, 68, 9, 38
2 | 3, 40, 73, 58, 10, 35, 96, 6, 65, 33
3 | 55, 67, 12, 97, 52, 73, 7, 76, 39, 50
4 | 59, 34, 20, 40, 92, 55, 11, 39, 93, 38
5 | 89, 89, 37, 52, 48, 86, 49, 3, 19, 50
6 | 84, 37, 68, 11, 20, 36, 46, 61, 52, 77
7 | 70, 90, 56, 55, 49, 76, 94, 28, 32, 23
8 | 5, 44, 92, 15, 53, 63, 87, 75, 61, 25
9 | 51, 58, 29, 30, 93, 94, 52, 72, 80, 27
10 | 1, 28, 82, 35, 89, 36, 10, 84, 85, 65
11 |
--------------------------------------------------------------------------------
/retired/data/file_2.txt:
--------------------------------------------------------------------------------
1 | 101, 31, 83,124, 41, 73, 0,121, 14, 98
2 | 137, 3, 77, 38,117, 79,104, 96, 62,117
3 | 99, 92,139, 29, 59, 30,116, 30, 74, 12
4 | 130,105,145,124, 39, 50, 66, 9,126, 24
5 | 32, 33, 34, 90, 43,140,136,149,140, 22
6 | 14, 8,138,101,136, 60, 41,110, 92,105
7 | 44, 76,104, 6,121,135, 41,132,131, 26
8 | 1, 1,112, 45,146, 29, 44,104, 75,122
9 | 132, 63, 70,109, 49, 75, 33, 36, 38,105
10 | 131, 71, 51, 79,109,146, 71, 27, 65,126
11 |
--------------------------------------------------------------------------------
/retired/ex_00_ray_tutorial_overview.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Ray Tutorial Basic Core APIs - Overview\n",
8 | "\n",
9 | "© 2021-2022, Anyscale. All Rights Reserved\n",
10 | "\n",
11 | "
\n",
12 | "\n",
13 | "## About This Tutorial\n",
14 | "\n",
15 | "In this tutorial, we'll cover the basic Ray Core APIs and its fundamental patterns. This is an introductory material, covering three basic distributed Ray core APIs patterns:\n",
16 | "\n",
17 | " * Remote Functions as Tasks\n",
18 | " * Remote Objects as Futures\n",
19 | " * Remote Classes as stateful Actors\n",
20 | " * A quick introduction to Ray Tune and Ray Serve\n",
21 | " \n",
22 | " \n",
23 | "There are other advance [Ray Patterns and Anti-patterns](https://docs.ray.io/en/latest/ray-design-patterns/index.html), which are not covered in this tutorial. Mainly applicable when writing more complex distributed applications, we recommend reading them to equip yourself to use Ray APIs more effectively.\n",
24 | "\n",
25 | "Additionally, we also introduce [XGBoost-Ray](https://github.com/ray-project/xgboost_ray), a drop-in replacement for XGBoost that allows you to do distributed HPO.\n",
26 | "\n",
27 | "\n",
28 | "See the instructions in the [README](./README.md) for setting up your environment to use this tutorial."
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "metadata": {},
34 | "source": [
35 | "| | Lesson | Description |\n",
36 | "| :-- | :----- | :---------- |\n",
37 | "| | **Module 1** | **Focus on Ray Core API Patterns and Ray CLI** |\n",
38 | "| 00 | [Ray Tutorial Overview](ex_00_ray_tutorial_overview) | Overview of this tutorial. |\n",
39 | "| 01 | [Ray Remote Functions ](ex_01_remote_funcs.ipynb) |The Remote Function as StateLess Tasks Pattern. |\n",
40 | "| 02 | [Ray Remote Objects](ex_02_remote_objs.ipynb) |The Remote Objects as Futures Pattern. |\n",
41 | "| 03 | [Ray Remote Classes](ex_03_remote_classes.ipynb) |The Remote Classes as Stateful Actors Pattern |\n",
42 | "| 04 | [Ray API Calls Tour](ex_04_exploring_ray_api_calls.ipynb) |A look at common Ray API calls |\n",
43 | "| 05 | [Running Ray Clusters](ex_05_running_ray_clusters.ipynb) | Ray Clusters from CLI |\n",
44 | "| | **Module 2** | **Brief introduction Ray XGBoost and Ray Tune for HPO** |\n",
45 | "| 06 | [Ray XGBoost and Ray Tune](ex_06_xgboost_train_tune.ipynb) | Ray Tune and XGBoost-Ray Drop-in replacement for Distributed HPO |\n",
46 | "| 07 | [Ray Tune and Scikit-learn](ex_07_ray_tune_scklearn.ipynb) | Ray Tune and Scikit-learn's TuneGridSearchCV Drop-in replacement for Distributed HPO |\n",
47 | "| | **Module 3** | **Brief introduction Ray Serve** |\n",
48 | "| 08 | [Ray Serve Model Serving Challenges](ex_08_model_serving_challenges.ipynb) | What are model serving challenges today |\n",
49 | "| 09 | [Ray Serve Accessing Deployments](ex_09_ray_serve_create_and_access_deployments.ipynb) | Multiple ways to access deployments |\n",
50 | "| 10 | [Ray Serve Example](ex_10_ray_serve_example.ipynb) | A Simple Ray Serve Example |\n",
51 | "| 11 | [Ray Serve Sentiment Analysis](ex_11_ray_serve_sentiment_tweets.ipynb) | Model composition model deployment pattern. A sentiment analysis model using HuggingFace 🤗 transformers |"
52 | ]
53 | }
54 | ],
55 | "metadata": {
56 | "kernelspec": {
57 | "display_name": "Python 3 (ipykernel)",
58 | "language": "python",
59 | "name": "python3"
60 | },
61 | "language_info": {
62 | "codemirror_mode": {
63 | "name": "ipython",
64 | "version": 3
65 | },
66 | "file_extension": ".py",
67 | "mimetype": "text/x-python",
68 | "name": "python",
69 | "nbconvert_exporter": "python",
70 | "pygments_lexer": "ipython3",
71 | "version": "3.10.6"
72 | }
73 | },
74 | "nbformat": 4,
75 | "nbformat_minor": 4
76 | }
77 |
--------------------------------------------------------------------------------
/retired/ex_02_remote_objs.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# A Guided Tour of Ray Core: Remote Objects\n",
8 | "\n",
9 | "© 2019-2022, Anyscale. All Rights Reserved\n"
10 | ]
11 | },
12 | {
13 | "cell_type": "markdown",
14 | "metadata": {},
15 | "source": [
16 | "[*Remote Objects*](https://docs.ray.io/en/latest/walkthrough.html#objects-in-ray)\n",
17 | "implement a [*shared-memory object store*](https://en.wikipedia.org/wiki/Shared_memory) pattern.\n",
18 | "\n",
19 | "Objects are immutable and can be accessed from anywhere on the cluster, as they are stored in the cluster shared memory.\n",
20 | "\n",
21 | "
\n",
22 | "\n",
23 | "In general, small objects are stored in their owner’s **in-process store** while large objects are stored in the **distributed object store**. This decision is meant to reduce the memory footprint and resolution time for each object. Note that in the latter case, a placeholder object is stored in the in-process store to indicate the object has been promoted to shared memory.\n",
24 | "\n",
25 | "In the case if there is no space in the shared-memory, objects are spilled over to disk. But the main point here is that\n",
26 | "shared-memory allows zero-copy to processes on the same worker node.\n",
27 | "\n",
28 | "
\n",
29 | "\n",
30 | "---"
31 | ]
32 | },
33 | {
34 | "cell_type": "markdown",
35 | "metadata": {},
36 | "source": [
37 | "## 2. Object references as Futures Pattern"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {},
43 | "source": [
44 | "First, let's start Ray…"
45 | ]
46 | },
47 | {
48 | "cell_type": "code",
49 | "execution_count": 2,
50 | "metadata": {},
51 | "outputs": [
52 | {
53 | "name": "stdout",
54 | "output_type": "stream",
55 | "text": [
56 | "RayContext(dashboard_url='127.0.0.1:8265', python_version='3.8.12', ray_version='2.0.0.dev0', ray_commit='{{RAY_COMMIT_SHA}}', address_info={'node_ip_address': '127.0.0.1', 'raylet_ip_address': '127.0.0.1', 'redis_address': None, 'object_store_address': '/tmp/ray/session_2022-04-25_11-16-09_358676_9733/sockets/plasma_store', 'raylet_socket_name': '/tmp/ray/session_2022-04-25_11-16-09_358676_9733/sockets/raylet', 'webui_url': '127.0.0.1:8265', 'session_dir': '/tmp/ray/session_2022-04-25_11-16-09_358676_9733', 'metrics_export_port': 61683, 'gcs_address': '127.0.0.1:54020', 'address': '127.0.0.1:54020', 'node_id': '55ab335477cac25f044eaa76483abca11cad960309aab0b89cb5c221'})\n"
57 | ]
58 | }
59 | ],
60 | "source": [
61 | "import logging\n",
62 | "from pprint import pprint\n",
63 | "import ray\n",
64 | "\n",
65 | "if ray.is_initialized:\n",
66 | " ray.shutdown()\n",
67 | "context = ray.init(logging_level=logging.ERROR)\n",
68 | "pprint(context)"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "execution_count": 4,
74 | "metadata": {},
75 | "outputs": [
76 | {
77 | "name": "stdout",
78 | "output_type": "stream",
79 | "text": [
80 | "Dashboard url: http://127.0.0.1:8265\n"
81 | ]
82 | }
83 | ],
84 | "source": [
85 | "print(f\"Dashboard url: http://{context.address_info['webui_url']}\")"
86 | ]
87 | },
88 | {
89 | "cell_type": "markdown",
90 | "metadata": {},
91 | "source": [
92 | "## Remote Objects example"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {},
98 | "source": [
99 | "To start, we'll define a remote object..."
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "execution_count": 5,
105 | "metadata": {},
106 | "outputs": [
107 | {
108 | "name": "stdout",
109 | "output_type": "stream",
110 | "text": [
111 | "CPU times: user 50.4 ms, sys: 18.8 ms, total: 69.2 ms\n",
112 | "Wall time: 88.6 ms\n"
113 | ]
114 | },
115 | {
116 | "data": {
117 | "text/plain": [
118 | "ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000001000000)"
119 | ]
120 | },
121 | "execution_count": 5,
122 | "metadata": {},
123 | "output_type": "execute_result"
124 | }
125 | ],
126 | "source": [
127 | "%%time\n",
128 | "num_list = [23, 42, 93]\n",
129 | "\n",
130 | "# returns an objectRef\n",
131 | "obj_ref = ray.put(num_list)\n",
132 | "obj_ref"
133 | ]
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "metadata": {},
138 | "source": [
139 | "Then retrieve the value of this object reference. This follows an object resolution protocol.\n",
140 | "\n",
141 | "
\n",
142 | "\n",
143 | "Small objects are resolved by copying them directly from the owner’s **in-process store**. For example, if the owner calls `ray.get`, the system looks up and deserializes the value from the local **in-process store**. If the owner submits a dependent task, it inlines the object by copying the value directly into the task description. Note that these objects are local to the owner process: if a borrower attempts to resolve the value, the object is promoted to shared memory, where it can be retrieved through the distributed object resolution protocol described next.\n",
144 | "\n",
145 | "Resolving a large object. The object `x` is initially created on Node 2, e.g., because the task that returned the value ran on that node. This shows the steps when the owner (the caller of the task) calls `ray.get`: \n",
146 | "\n",
147 | " 1) Lookup object’s locations at the owner. \n",
148 | " 2) Select a location and send a request for a copy of the object. \n",
149 | " 3) Receive the object.\n",
150 | "\n"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "execution_count": 6,
156 | "metadata": {},
157 | "outputs": [
158 | {
159 | "data": {
160 | "text/plain": [
161 | "[23, 42, 93]"
162 | ]
163 | },
164 | "execution_count": 6,
165 | "metadata": {},
166 | "output_type": "execute_result"
167 | }
168 | ],
169 | "source": [
170 | "val = ray.get(obj_ref)\n",
171 | "val"
172 | ]
173 | },
174 | {
175 | "cell_type": "markdown",
176 | "metadata": {},
177 | "source": [
178 | "Let's combine use of a remote function with a remote object, to illustrate *composable futures*:"
179 | ]
180 | },
181 | {
182 | "cell_type": "code",
183 | "execution_count": 7,
184 | "metadata": {},
185 | "outputs": [],
186 | "source": [
187 | "@ray.remote\n",
188 | "def my_function (num_list):\n",
189 | " return sum(num_list)"
190 | ]
191 | },
192 | {
193 | "cell_type": "markdown",
194 | "metadata": {},
195 | "source": [
196 | "In other words, the remote function `myfunction()` will sum the list of integers in the remote object `num_list`:"
197 | ]
198 | },
199 | {
200 | "cell_type": "code",
201 | "execution_count": 8,
202 | "metadata": {},
203 | "outputs": [],
204 | "source": [
205 | "calc_ref = my_function.remote(obj_ref)"
206 | ]
207 | },
208 | {
209 | "cell_type": "code",
210 | "execution_count": 9,
211 | "metadata": {},
212 | "outputs": [
213 | {
214 | "data": {
215 | "text/plain": [
216 | "158"
217 | ]
218 | },
219 | "execution_count": 9,
220 | "metadata": {},
221 | "output_type": "execute_result"
222 | }
223 | ],
224 | "source": [
225 | "result = ray.get(calc_ref)\n",
226 | "result"
227 | ]
228 | },
229 | {
230 | "cell_type": "markdown",
231 | "metadata": {},
232 | "source": [
233 | "You can gather the values of multiple object references in parallel using comprehension:\n",
234 | " 1. Each value is put in the object store and its `ObjRefID` is immediately returned\n",
235 | " 2. The comprehsion constructs a list of `ObjRefIDs` for each element in the loop\n",
236 | " 3. A final `get(list_obj_refs`) is invoked to fetch the list"
237 | ]
238 | },
239 | {
240 | "cell_type": "code",
241 | "execution_count": 10,
242 | "metadata": {},
243 | "outputs": [
244 | {
245 | "data": {
246 | "text/plain": [
247 | "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
248 | ]
249 | },
250 | "execution_count": 10,
251 | "metadata": {},
252 | "output_type": "execute_result"
253 | }
254 | ],
255 | "source": [
256 | "results = ray.get([ray.put(i) for i in range(10)])\n",
257 | "results"
258 | ]
259 | },
260 | {
261 | "cell_type": "markdown",
262 | "metadata": {},
263 | "source": [
264 | "### What about long running tasks?\n",
265 | "\n",
266 | "Now let's set a timeout to return early from attempted access of a remote object that is blocking for too long..."
267 | ]
268 | },
269 | {
270 | "cell_type": "code",
271 | "execution_count": 11,
272 | "metadata": {},
273 | "outputs": [],
274 | "source": [
275 | "import time\n",
276 | "\n",
277 | "@ray.remote\n",
278 | "def long_running_function ():\n",
279 | " time.sleep(10)\n",
280 | " return 42"
281 | ]
282 | },
283 | {
284 | "cell_type": "markdown",
285 | "metadata": {},
286 | "source": [
287 | "You can control how long you want to wait for the task to finish"
288 | ]
289 | },
290 | {
291 | "cell_type": "code",
292 | "execution_count": 12,
293 | "metadata": {},
294 | "outputs": [
295 | {
296 | "name": "stdout",
297 | "output_type": "stream",
298 | "text": [
299 | "`get` timed out\n",
300 | "CPU times: user 32.2 ms, sys: 28.8 ms, total: 61 ms\n",
301 | "Wall time: 6.02 s\n"
302 | ]
303 | }
304 | ],
305 | "source": [
306 | "%%time\n",
307 | "\n",
308 | "from ray.exceptions import GetTimeoutError\n",
309 | "\n",
310 | "obj_ref = long_running_function.remote()\n",
311 | "\n",
312 | "try:\n",
313 | " ray.get(obj_ref, timeout=6)\n",
314 | "except GetTimeoutError:\n",
315 | " print(\"`get` timed out\")"
316 | ]
317 | },
318 | {
319 | "cell_type": "code",
320 | "execution_count": 19,
321 | "metadata": {},
322 | "outputs": [],
323 | "source": [
324 | "ray.shutdown()"
325 | ]
326 | },
327 | {
328 | "cell_type": "markdown",
329 | "metadata": {},
330 | "source": [
331 | "### Exercises\n",
332 | "\n",
333 | "1. Send a list of object references returned by `ray.put(x)` \n",
334 | "2. Use comprehension to construct this list and send it to `my_function.remote(list_of_object_refs)` to return the sum of the list\n",
335 | "3. Create a python object, use `ray.put(pobj)` and `ray.get(pobj)`"
336 | ]
337 | },
338 | {
339 | "cell_type": "markdown",
340 | "metadata": {},
341 | "source": [
342 | "### Homework\n",
343 | "\n",
344 | "1. Read references to get advanced deep dives"
345 | ]
346 | },
347 | {
348 | "cell_type": "markdown",
349 | "metadata": {},
350 | "source": [
351 | "## References\n",
352 | "\n",
353 | " * [Ray Architecture Reference](https://docs.google.com/document/d/1lAy0Owi-vPz2jEqBSaHNQcy2IBSDEHyXNOQZlGuj93c/preview#)\n",
354 | " * [Ray Internals: A peek at ray,get](https://www.youtube.com/watch?v=a1kNnQu6vGw)\n",
355 | " * [Ray Internals: Object management with Ownership Model](https://www.anyscale.com/events/2021/06/22/ray-internals-object-management-with-the-ownership-model)\n",
356 | " * [Deep Dive into Ray scheduling Policies](https://www.anyscale.com/events/2021/06/23/a-deep-dive-into-rays-scheduling-policy)\n",
357 | " * [Redis in Ray: Past and future](https://www.anyscale.com/blog/redis-in-ray-past-and-future)\n",
358 | " * [StackOverFlow: How Ray Shares Data](https://stackoverflow.com/questions/58082023/how-exactly-does-ray-share-data-to-workers/71500979#71500979)\n",
359 | " "
360 | ]
361 | }
362 | ],
363 | "metadata": {
364 | "kernelspec": {
365 | "display_name": "Python 3 (ipykernel)",
366 | "language": "python",
367 | "name": "python3"
368 | },
369 | "language_info": {
370 | "codemirror_mode": {
371 | "name": "ipython",
372 | "version": 3
373 | },
374 | "file_extension": ".py",
375 | "mimetype": "text/x-python",
376 | "name": "python",
377 | "nbconvert_exporter": "python",
378 | "pygments_lexer": "ipython3",
379 | "version": "3.8.12"
380 | }
381 | },
382 | "nbformat": 4,
383 | "nbformat_minor": 4
384 | }
385 |
--------------------------------------------------------------------------------
/retired/ex_07_ray_tune_scklearn.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "50156943",
6 | "metadata": {},
7 | "source": [
8 | "# Ray Crash Course - Distributed HPO with Ray Tune's TuneGridSearchCV and Scikit-Learn\n",
9 | "\n",
10 | "© 2019-2022, Anyscale. All Rights Reserved\n",
11 | "\n",
12 | "This demo introduces **Ray tune's** key concepts using a classification example. Basically, there are three basic steps or Ray Tune pattern for you as a newcomer to get started with using Ray Tune. We'll use a drop-in replacement for normal Scikit-learn's `GridSearchCV` with distributed Ray Tune's `TuneGridSearchCV`.\n",
13 | "\n",
14 | "See also the [Understanding Hyperparameter Tuning](https://github.com/anyscale/academy/blob/main/ray-tune/02-Understanding-Hyperparameter-Tuning.ipynb) notebook and the [Tune documentation](http://tune.io), in particular, the [API reference](https://docs.ray.io/en/latest/tune/api_docs/overview.html). \n"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 22,
20 | "id": "eed803cc",
21 | "metadata": {},
22 | "outputs": [],
23 | "source": [
24 | "# Import Tune's replacement\n",
25 | "from ray.tune.sklearn import TuneGridSearchCV\n",
26 | "\n",
27 | "# Other relevant imports\n",
28 | "from sklearn.model_selection import train_test_split\n",
29 | "\n",
30 | "# Use the stochastic gradient descent (SGD) classifier\n",
31 | "from sklearn.linear_model import SGDClassifier\n",
32 | "\n",
33 | "# import the classification dataset\n",
34 | "from sklearn.datasets import make_classification\n",
35 | "import numpy as np\n",
36 | "import time\n",
37 | "import logging\n",
38 | "import ray"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 23,
44 | "id": "f93759e0",
45 | "metadata": {},
46 | "outputs": [
47 | {
48 | "name": "stderr",
49 | "output_type": "stream",
50 | "text": [
51 | "2022-04-19 11:19:38,906\tINFO services.py:1460 -- View the Ray dashboard at \u001b[1m\u001b[32mhttp://127.0.0.1:8265\u001b[39m\u001b[22m\n"
52 | ]
53 | }
54 | ],
55 | "source": [
56 | "CONNECT_TO_ANYSCALE=False\n",
57 | "if ray.is_initialized:\n",
58 | " ray.shutdown()\n",
59 | " if CONNECT_TO_ANYSCALE:\n",
60 | " ray.init(\"anyscale://jsd-ray-core-tutorial\")\n",
61 | " else:\n",
62 | " ray.init()"
63 | ]
64 | },
65 | {
66 | "cell_type": "markdown",
67 | "id": "d9fc8350",
68 | "metadata": {},
69 | "source": [
70 | "### Create Feature Set\n",
71 | "\n",
72 | " * 250K rows\n",
73 | " * 250 features\n",
74 | " * 2 classes"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": 24,
80 | "id": "13e7b4fc",
81 | "metadata": {},
82 | "outputs": [],
83 | "source": [
84 | "def create_classification_data() -> (np.ndarray, np.ndarray):\n",
85 | " X, y = make_classification(\n",
86 | " n_samples=250000,\n",
87 | " n_features=250,\n",
88 | " n_informative=50,\n",
89 | " n_redundant=0,\n",
90 | " n_classes=2,\n",
91 | " class_sep=2.5)\n",
92 | " return X, y"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "id": "f96c690a",
98 | "metadata": {},
99 | "source": [
100 | "### Create classification data and define parameter search space"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": 25,
106 | "id": "a20ef947",
107 | "metadata": {},
108 | "outputs": [],
109 | "source": [
110 | "X, y = create_classification_data()\n",
111 | "# Split the dataset into train and test sets\n",
112 | "x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=10000)\n",
113 | "\n",
114 | "# Example parameters grid to tune from SGDClassifier\n",
115 | "parameter_grid = {\"alpha\": [1e-4, 1e-1, 1], \"epsilon\": [0.01, 0.1]}"
116 | ]
117 | },
118 | {
119 | "cell_type": "markdown",
120 | "id": "7c2a5ee5",
121 | "metadata": {},
122 | "source": [
123 | "## Use Ray's Scikit-learn drop-in replacement TuneGridSearchCV\n",
124 | "Use all cores on a Ray Cluster or local host to tune "
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": 26,
130 | "id": "2e100cde",
131 | "metadata": {},
132 | "outputs": [],
133 | "source": [
134 | "# Now let's do with Tune's in-place replacement\n",
135 | "# Note: If early_stopping=True, TuneGridSearchCV will default to using Tune’s ASHAScheduler.\n",
136 | "tune_sklearn = TuneGridSearchCV(SGDClassifier(), \n",
137 | " parameter_grid,\n",
138 | " early_stopping=True,\n",
139 | " max_iters=30,\n",
140 | " n_jobs=12, # Use 40 cores if running on a cluster\n",
141 | " mode=\"min\",\n",
142 | " verbose=True)"
143 | ]
144 | },
145 | {
146 | "cell_type": "code",
147 | "execution_count": 27,
148 | "id": "a74c1d1a",
149 | "metadata": {},
150 | "outputs": [
151 | {
152 | "data": {
153 | "text/html": [
154 | "== Status ==
Current time: 2022-04-19 11:21:00 (running for 00:01:00.03)
Memory usage on this node: 14.4/32.0 GiB
Using AsyncHyperBand: num_stopped=4\n",
155 | "Bracket: Iter 16.000: -0.9791052083333334 | Iter 4.000: -0.9734739583333334 | Iter 1.000: -0.9747270833333332
Resources requested: 0/12 CPUs, 0/0 GPUs, 0.0/15.61 GiB heap, 0.0/2.0 GiB objects
Current best trial: 52e75_00003 with average_test_score=0.9806791666666668 and parameters={'early_stopping': True, 'early_stop_type': , 'groups': None, 'cv': StratifiedKFold(n_splits=5, random_state=None, shuffle=False), 'fit_params': {}, 'scoring': {'score': }, 'max_iters': 30, 'return_train_score': False, 'n_jobs': 1, 'metric_name': 'average_test_score', 'alpha': 0.0001, 'epsilon': 0.1}
Result logdir: /Users/jules/ray_results/_Trainable_2022-04-19_11-19-59
Number of trials: 6/6 (6 TERMINATED)
"
156 | ],
157 | "text/plain": [
158 | ""
159 | ]
160 | },
161 | "metadata": {},
162 | "output_type": "display_data"
163 | },
164 | {
165 | "name": "stderr",
166 | "output_type": "stream",
167 | "text": [
168 | "2022-04-19 11:21:00,108\tINFO tune.py:702 -- Total run time: 60.15 seconds (60.03 seconds for the tuning loop).\n"
169 | ]
170 | },
171 | {
172 | "name": "stdout",
173 | "output_type": "stream",
174 | "text": [
175 | "CPU times: user 2.03 s, sys: 1.28 s, total: 3.31 s\n",
176 | "Wall time: 1min 1s\n"
177 | ]
178 | },
179 | {
180 | "data": {
181 | "text/plain": [
182 | "TuneGridSearchCV(early_stopping=True, estimator=SGDClassifier(), max_iters=30,\n",
183 | " mode='min', n_jobs=12,\n",
184 | " param_grid={'alpha': [0.0001, 0.1, 1], 'epsilon': [0.01, 0.1]},\n",
185 | " sk_n_jobs=1, verbose=True)"
186 | ]
187 | },
188 | "execution_count": 27,
189 | "metadata": {},
190 | "output_type": "execute_result"
191 | }
192 | ],
193 | "source": [
194 | "%%time\n",
195 | "tune_sklearn.fit(x_train, y_train)"
196 | ]
197 | },
198 | {
199 | "cell_type": "code",
200 | "execution_count": 29,
201 | "id": "116b90ee",
202 | "metadata": {},
203 | "outputs": [
204 | {
205 | "name": "stdout",
206 | "output_type": "stream",
207 | "text": [
208 | "Ray Tune Scikit-learn TuneGridSearchCV Best params: {'alpha': 0.1, 'epsilon': 0.1}\n"
209 | ]
210 | }
211 | ],
212 | "source": [
213 | "print(f\"Ray Tune Scikit-learn TuneGridSearchCV Best params: {tune_sklearn.best_params}\")"
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": 30,
219 | "id": "4214cf5d-ce55-4a79-a294-93523b1a636c",
220 | "metadata": {},
221 | "outputs": [],
222 | "source": [
223 | "ray.shutdown()"
224 | ]
225 | },
226 | {
227 | "cell_type": "markdown",
228 | "id": "9d9517b3-c139-4cc8-84cd-12a1aa224385",
229 | "metadata": {},
230 | "source": [
231 | "### Homework\n",
232 | "\n",
233 | "1. Try some [Tune How-to guides](https://docs.ray.io/en/latest/tune/examples/index.html) "
234 | ]
235 | }
236 | ],
237 | "metadata": {
238 | "kernelspec": {
239 | "display_name": "Python 3 (ipykernel)",
240 | "language": "python",
241 | "name": "python3"
242 | },
243 | "language_info": {
244 | "codemirror_mode": {
245 | "name": "ipython",
246 | "version": 3
247 | },
248 | "file_extension": ".py",
249 | "mimetype": "text/x-python",
250 | "name": "python",
251 | "nbconvert_exporter": "python",
252 | "pygments_lexer": "ipython3",
253 | "version": "3.8.13"
254 | }
255 | },
256 | "nbformat": 4,
257 | "nbformat_minor": 5
258 | }
259 |
--------------------------------------------------------------------------------
/retired/ex_09_ray_serve_create_and_access_deployments.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "d6e4dfe1-144a-4142-b3a2-9cd5fc20ced5",
6 | "metadata": {},
7 | "source": [
8 | "# Ray Serve - Creating, Deploying and Accessing Deployments\n",
9 | "\n",
10 | "© 2019-2022, Anyscale. All Rights Reserved\n",
11 | "\n",
12 | "This brief tutorial shows how to create, deploy, and expose access to\n",
13 | "deployment models, using the simple Ray Serve deployment APIs.\n",
14 | "Once deployed, you can send requests to deployments via two methods:\n",
15 | "\n",
16 | " 1. ServerHandle API\n",
17 | " 2. HTTP\n",
18 | " \n",
19 | "
"
20 | ]
21 | },
22 | {
23 | "cell_type": "code",
24 | "execution_count": 1,
25 | "id": "6162fac5-4fa5-4553-9a21-8ac8dab4a4a2",
26 | "metadata": {},
27 | "outputs": [],
28 | "source": [
29 | "import os\n",
30 | "from random import random\n",
31 | "\n",
32 | "import requests\n",
33 | "import starlette\n",
34 | "from starlette.requests import Request\n",
35 | "import ray\n",
36 | "from ray import serve"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "id": "05706639-da47-4826-80b8-b8915ca25696",
42 | "metadata": {},
43 | "source": [
44 | "A simple example model stored in a pickled format at an accessible path\n",
45 | "that can be reloaded and deserialized into a model instance. Once deployed\n",
46 | "in Ray Serve, we can use it for prediction. The prediction is a fake condition,\n",
47 | "based on threshold of weight greater than 0.5."
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": 2,
53 | "id": "0a6596d7-e3f1-42cb-97f2-70f76b57450b",
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "class Model:\n",
58 | " def __init__(self, path):\n",
59 | " self.path = path\n",
60 | "\n",
61 | " def predict(self, data):\n",
62 | " return random() + data if data > 0.5 else data"
63 | ]
64 | },
65 | {
66 | "cell_type": "code",
67 | "execution_count": 3,
68 | "id": "96ab2dd9-bcd3-4756-ac04-d0771a7a5441",
69 | "metadata": {},
70 | "outputs": [],
71 | "source": [
72 | "@serve.deployment\n",
73 | "class Deployment:\n",
74 | " # Take in a path to load your desired model\n",
75 | " def __init__(self, path: str) -> None:\n",
76 | " self.path = path\n",
77 | " self.model = Model(path)\n",
78 | " # Get the pid on which this deployment is running on\n",
79 | " self.pid = os.getpid()\n",
80 | "\n",
81 | " # Deployments are callable. Here we simply return a prediction from\n",
82 | " # our request\n",
83 | " def __call__(self, starlette_request) -> str:\n",
84 | " # Request came via an HTTP\n",
85 | " if isinstance(starlette_request, starlette.requests.Request):\n",
86 | " data = starlette_request.query_params['data']\n",
87 | " else:\n",
88 | " # Request came via a ServerHandle API method call.\n",
89 | " data = starlette_request\n",
90 | " pred = self.model.predict(float(data))\n",
91 | " return f\"(pid: {self.pid}); path: {self.path}; data: {float(data):.3f}; prediction: {pred:.3f}\""
92 | ]
93 | },
94 | {
95 | "cell_type": "markdown",
96 | "id": "8ce34a8a-9fe0-4c02-bf83-9b6210b08e7f",
97 | "metadata": {},
98 | "source": [
99 | "Start a Ray Serve instance. This will automatically start or connect to an existing Ray cluster."
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "execution_count": 4,
105 | "id": "b86ad83f-19c9-4410-b635-955497ecc20f",
106 | "metadata": {},
107 | "outputs": [
108 | {
109 | "name": "stderr",
110 | "output_type": "stream",
111 | "text": [
112 | "2022-04-19 11:28:32,906\tINFO services.py:1460 -- View the Ray dashboard at \u001b[1m\u001b[32mhttp://127.0.0.1:8267\u001b[39m\u001b[22m\n",
113 | "\u001b[2m\u001b[36m(ServeController pid=3502)\u001b[0m 2022-04-19 11:28:36,828\tINFO checkpoint_path.py:15 -- Using RayInternalKVStore for controller checkpoint and recovery.\n",
114 | "\u001b[2m\u001b[36m(ServeController pid=3502)\u001b[0m 2022-04-19 11:28:36,933\tINFO http_state.py:106 -- Starting HTTP proxy with name 'SERVE_CONTROLLER_ACTOR:wJcaTj:SERVE_PROXY_ACTOR-node:127.0.0.1-0' on node 'node:127.0.0.1-0' listening on '127.0.0.1:8000'\n",
115 | "2022-04-19 11:28:38,370\tINFO api.py:797 -- Started Serve instance in namespace 'serve'.\n"
116 | ]
117 | },
118 | {
119 | "data": {
120 | "text/plain": [
121 | ""
122 | ]
123 | },
124 | "execution_count": 4,
125 | "metadata": {},
126 | "output_type": "execute_result"
127 | }
128 | ],
129 | "source": [
130 | "serve.start()"
131 | ]
132 | },
133 | {
134 | "cell_type": "markdown",
135 | "id": "5de7ed24-649a-403c-ad76-085cf33c4eed",
136 | "metadata": {},
137 | "source": [
138 | "Create two distinct deployments of the same class as two replicas. \n",
139 | "Associate each deployment with a unique 'name'.This name can be used as to fetch its respective serve handle.\n",
140 | "See code below for method 1."
141 | ]
142 | },
143 | {
144 | "cell_type": "code",
145 | "execution_count": 5,
146 | "id": "ffd04a68-e299-4647-bb75-2abf6492c2f4",
147 | "metadata": {},
148 | "outputs": [
149 | {
150 | "name": "stderr",
151 | "output_type": "stream",
152 | "text": [
153 | "2022-04-19 11:28:38,388\tINFO api.py:618 -- Updating deployment 'rep-1'. component=serve deployment=rep-1\n",
154 | "\u001b[2m\u001b[36m(HTTPProxyActor pid=3510)\u001b[0m INFO: Started server process [3510]\n",
155 | "\u001b[2m\u001b[36m(ServeController pid=3502)\u001b[0m 2022-04-19 11:28:38,426\tINFO deployment_state.py:1210 -- Adding 2 replicas to deployment 'rep-1'. component=serve deployment=rep-1\n",
156 | "2022-04-19 11:28:40,400\tINFO api.py:633 -- Deployment 'rep-1' is ready at `http://127.0.0.1:8000/rep-1`. component=serve deployment=rep-1\n",
157 | "2022-04-19 11:28:40,407\tINFO api.py:618 -- Updating deployment 'rep-2'. component=serve deployment=rep-2\n",
158 | "\u001b[2m\u001b[36m(ServeController pid=3502)\u001b[0m 2022-04-19 11:28:40,461\tINFO deployment_state.py:1210 -- Adding 2 replicas to deployment 'rep-2'. component=serve deployment=rep-2\n",
159 | "2022-04-19 11:28:42,417\tINFO api.py:633 -- Deployment 'rep-2' is ready at `http://127.0.0.1:8000/rep-2`. component=serve deployment=rep-2\n"
160 | ]
161 | }
162 | ],
163 | "source": [
164 | "Deployment.options(name=\"rep-1\", num_replicas=2).deploy(\"/model/rep-1.pkl\")\n",
165 | "Deployment.options(name=\"rep-2\", num_replicas=2).deploy(\"/model/rep-2.pkl\")"
166 | ]
167 | },
168 | {
169 | "cell_type": "markdown",
170 | "id": "1afacbbf-e3ad-4312-8d53-39ac90d81a2b",
171 | "metadata": {},
172 | "source": [
173 | "### Get the current list of deployment\n"
174 | ]
175 | },
176 | {
177 | "cell_type": "code",
178 | "execution_count": 6,
179 | "id": "a1ebe3d9-5b11-4e39-81a3-e4fb44f98f7b",
180 | "metadata": {},
181 | "outputs": [
182 | {
183 | "name": "stdout",
184 | "output_type": "stream",
185 | "text": [
186 | "{'rep-1': Deployment(name=rep-1,version=None,route_prefix=/rep-1), 'rep-2': Deployment(name=rep-2,version=None,route_prefix=/rep-2)}\n"
187 | ]
188 | }
189 | ],
190 | "source": [
191 | "print(serve.list_deployments())"
192 | ]
193 | },
194 | {
195 | "cell_type": "markdown",
196 | "id": "3d5b149f-b36f-44d5-9fdf-e04d3162a9ed",
197 | "metadata": {},
198 | "source": [
199 | "### Method 1: Access each deployment using the ServerHandle API"
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": 7,
205 | "id": "4fb8c5a8-04e2-4c66-8854-795839bc0c26",
206 | "metadata": {},
207 | "outputs": [
208 | {
209 | "name": "stderr",
210 | "output_type": "stream",
211 | "text": [
212 | "2022-04-19 11:28:46,570\tWARNING api.py:488 -- You are retrieving a sync handle inside an asyncio loop. Try getting client.get_handle(.., sync=False) to get better performance. Learn more at https://docs.ray.io/en/master/serve/http-servehandle.html#sync-and-async-handles\n",
213 | "2022-04-19 11:28:46,587\tWARNING api.py:488 -- You are retrieving a sync handle inside an asyncio loop. Try getting client.get_handle(.., sync=False) to get better performance. Learn more at https://docs.ray.io/en/master/serve/http-servehandle.html#sync-and-async-handles\n"
214 | ]
215 | },
216 | {
217 | "name": "stdout",
218 | "output_type": "stream",
219 | "text": [
220 | "handle name : rep-1\n",
221 | "prediction : (pid: 3537); path: /model/rep-1.pkl; data: 0.553; prediction: 1.232\n",
222 | "--\n",
223 | "handle name : rep-2\n",
224 | "prediction : (pid: 3540); path: /model/rep-2.pkl; data: 0.965; prediction: 1.644\n",
225 | "--\n",
226 | "handle name : rep-1\n",
227 | "prediction : (pid: 3536); path: /model/rep-1.pkl; data: 0.415; prediction: 0.415\n",
228 | "--\n",
229 | "handle name : rep-2\n",
230 | "prediction : (pid: 3541); path: /model/rep-2.pkl; data: 0.515; prediction: 1.194\n",
231 | "--\n"
232 | ]
233 | }
234 | ],
235 | "source": [
236 | "for _ in range(2):\n",
237 | " for d_name in [\"rep-1\", \"rep-2\"]:\n",
238 | " # Get handle to the each deployment and invoke its method.\n",
239 | " # Which replica the request is dispatched to is determined\n",
240 | " # by the Router actor.\n",
241 | " handle = serve.get_deployment(d_name).get_handle()\n",
242 | " print(f\"handle name : {d_name}\")\n",
243 | " print(f\"prediction : {ray.get(handle.remote(random()))}\")\n",
244 | " print(\"-\" * 2)"
245 | ]
246 | },
247 | {
248 | "cell_type": "markdown",
249 | "id": "e22863fa-7128-4b1f-853c-5a77723ff344",
250 | "metadata": {},
251 | "source": [
252 | "### Method 2: Access deployment via HTTP Request"
253 | ]
254 | },
255 | {
256 | "cell_type": "code",
257 | "execution_count": 8,
258 | "id": "6d4bcce3-30b5-4baa-b67d-d6a575a30edb",
259 | "metadata": {},
260 | "outputs": [
261 | {
262 | "name": "stdout",
263 | "output_type": "stream",
264 | "text": [
265 | "handle name : rep-1\n",
266 | "prediction : (pid: 3537); path: /model/rep-1.pkl; data: 0.643; prediction: 1.273\n",
267 | "handle name : rep-2\n",
268 | "prediction : (pid: 3540); path: /model/rep-2.pkl; data: 0.247; prediction: 0.247\n",
269 | "handle name : rep-1\n",
270 | "prediction : (pid: 3536); path: /model/rep-1.pkl; data: 0.938; prediction: 1.617\n",
271 | "handle name : rep-2\n",
272 | "prediction : (pid: 3541); path: /model/rep-2.pkl; data: 0.493; prediction: 0.493\n"
273 | ]
274 | }
275 | ],
276 | "source": [
277 | "for _ in range(2):\n",
278 | " for d_name in [\"rep-1\", \"rep-2\"]:\n",
279 | " # Send HTTP request along with data payload\n",
280 | " url = f\"http://127.0.0.1:8000/{d_name}\"\n",
281 | " print(f\"handle name : {d_name}\")\n",
282 | " print(f\"prediction : {requests.get(url, params={'data': random()}).text}\")"
283 | ]
284 | },
285 | {
286 | "cell_type": "code",
287 | "execution_count": 9,
288 | "id": "e87a6d90-805a-4b4a-a37c-70b4e0715589",
289 | "metadata": {},
290 | "outputs": [
291 | {
292 | "name": "stderr",
293 | "output_type": "stream",
294 | "text": [
295 | "\u001b[2m\u001b[36m(ServeController pid=3502)\u001b[0m 2022-04-19 11:29:04,136\tINFO deployment_state.py:1236 -- Removing 2 replicas from deployment 'rep-1'. component=serve deployment=rep-1\n",
296 | "\u001b[2m\u001b[36m(ServeController pid=3502)\u001b[0m 2022-04-19 11:29:04,140\tINFO deployment_state.py:1236 -- Removing 2 replicas from deployment 'rep-2'. component=serve deployment=rep-2\n"
297 | ]
298 | }
299 | ],
300 | "source": [
301 | "serve.shutdown()"
302 | ]
303 | },
304 | {
305 | "cell_type": "markdown",
306 | "id": "3c1e4e92-2eb0-4a18-9ffa-c24893c929e4",
307 | "metadata": {},
308 | "source": [
309 | "### Exercises\n",
310 | "\n",
311 | "Here are some things you can try:\n",
312 | "\n",
313 | "1. For each method, send ten requests\n",
314 | "2. Increase number of replicas\n",
315 | "3. Do requests get sent to different replicas? (check the pids or the Ray Dashboard)"
316 | ]
317 | }
318 | ],
319 | "metadata": {
320 | "kernelspec": {
321 | "display_name": "Python 3 (ipykernel)",
322 | "language": "python",
323 | "name": "python3"
324 | },
325 | "language_info": {
326 | "codemirror_mode": {
327 | "name": "ipython",
328 | "version": 3
329 | },
330 | "file_extension": ".py",
331 | "mimetype": "text/x-python",
332 | "name": "python",
333 | "nbconvert_exporter": "python",
334 | "pygments_lexer": "ipython3",
335 | "version": "3.10.6"
336 | }
337 | },
338 | "nbformat": 4,
339 | "nbformat_minor": 5
340 | }
341 |
--------------------------------------------------------------------------------
/retired/ex_10_ray_serve_example.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Ray Serve - Model Serving\n",
8 | "\n",
9 | "© 2019-2022, Anyscale. All Rights Reserved\n"
10 | ]
11 | },
12 | {
13 | "cell_type": "markdown",
14 | "metadata": {},
15 | "source": [
16 | "Now we'll explore a short example for Ray Serve. This example is from the Ray Serve [scikit-learn example.](https://docs.ray.io/en/latest/serve/tutorials/sklearn.html)\n",
17 | "\n",
18 | "See also the Serve documentation's [mini-tutorials](https://docs.ray.io/en/latest/serve/tutorials/index.html) for using Serve with various frameworks.\n",
19 | "\n",
20 | "
"
21 | ]
22 | },
23 | {
24 | "cell_type": "code",
25 | "execution_count": 1,
26 | "metadata": {},
27 | "outputs": [],
28 | "source": [
29 | "import ray\n",
30 | "from ray import serve\n",
31 | "import requests # for making web requests\n",
32 | "import tempfile\n",
33 | "\n",
34 | "import os\n",
35 | "import pickle\n",
36 | "import json\n",
37 | "import numpy as np"
38 | ]
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": 2,
43 | "metadata": {},
44 | "outputs": [
45 | {
46 | "name": "stderr",
47 | "output_type": "stream",
48 | "text": [
49 | "2022-04-19 11:29:41,124\tINFO services.py:1460 -- View the Ray dashboard at \u001b[1m\u001b[32mhttp://127.0.0.1:8268\u001b[39m\u001b[22m\n",
50 | "\u001b[2m\u001b[36m(ServeController pid=3675)\u001b[0m 2022-04-19 11:29:45,067\tINFO checkpoint_path.py:15 -- Using RayInternalKVStore for controller checkpoint and recovery.\n",
51 | "\u001b[2m\u001b[36m(ServeController pid=3675)\u001b[0m 2022-04-19 11:29:45,172\tINFO http_state.py:106 -- Starting HTTP proxy with name 'SERVE_CONTROLLER_ACTOR:BkVkza:SERVE_PROXY_ACTOR-node:127.0.0.1-0' on node 'node:127.0.0.1-0' listening on '127.0.0.1:8000'\n",
52 | "2022-04-19 11:29:46,505\tINFO api.py:797 -- Started Serve instance in namespace 'serve'.\n"
53 | ]
54 | },
55 | {
56 | "data": {
57 | "text/plain": [
58 | ""
59 | ]
60 | },
61 | "execution_count": 2,
62 | "metadata": {},
63 | "output_type": "execute_result"
64 | }
65 | ],
66 | "source": [
67 | "serve.start()"
68 | ]
69 | },
70 | {
71 | "cell_type": "markdown",
72 | "metadata": {},
73 | "source": [
74 | "## Create a Model to Serve \n",
75 | "\n",
76 | "We'll begin by training a classifier with the Iris data we used before, this time using [scikit-learn](https://scikit-learn.org/stable/). The details aren't too important for our purposes, except for the fact we'll save the trained model to disk for subsequent serving."
77 | ]
78 | },
79 | {
80 | "cell_type": "code",
81 | "execution_count": 3,
82 | "metadata": {},
83 | "outputs": [
84 | {
85 | "name": "stderr",
86 | "output_type": "stream",
87 | "text": [
88 | "\u001b[2m\u001b[36m(HTTPProxyActor pid=3677)\u001b[0m INFO: Started server process [3677]\n"
89 | ]
90 | }
91 | ],
92 | "source": [
93 | "import sklearn\n",
94 | "from sklearn.datasets import load_iris\n",
95 | "from sklearn.ensemble import GradientBoostingClassifier\n",
96 | "from sklearn.metrics import mean_squared_error"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": 4,
102 | "metadata": {},
103 | "outputs": [],
104 | "source": [
105 | "# Load data\n",
106 | "iris_dataset = load_iris()\n",
107 | "data, target, target_names = iris_dataset[\"data\"], iris_dataset[\n",
108 | " \"target\"], iris_dataset[\"target_names\"]"
109 | ]
110 | },
111 | {
112 | "cell_type": "code",
113 | "execution_count": 5,
114 | "metadata": {},
115 | "outputs": [],
116 | "source": [
117 | "# Instantiate model\n",
118 | "model = GradientBoostingClassifier()"
119 | ]
120 | },
121 | {
122 | "cell_type": "code",
123 | "execution_count": 6,
124 | "metadata": {},
125 | "outputs": [],
126 | "source": [
127 | "# Training and validation split\n",
128 | "data, target = sklearn.utils.shuffle(data, target)\n",
129 | "train_x, train_y = data[:100], target[:100]\n",
130 | "val_x, val_y = data[100:], target[100:]"
131 | ]
132 | },
133 | {
134 | "cell_type": "code",
135 | "execution_count": 7,
136 | "metadata": {},
137 | "outputs": [
138 | {
139 | "name": "stdout",
140 | "output_type": "stream",
141 | "text": [
142 | "MSE: 0.02\n"
143 | ]
144 | }
145 | ],
146 | "source": [
147 | "# Train and evaluate models\n",
148 | "model.fit(train_x, train_y)\n",
149 | "print(\"MSE:\", mean_squared_error(model.predict(val_x), val_y))"
150 | ]
151 | },
152 | {
153 | "cell_type": "markdown",
154 | "metadata": {
155 | "tags": []
156 | },
157 | "source": [
158 | "Save the model and label to file. This could also be S3 or other \"global\" place or fetched from the model regsitry."
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 8,
164 | "metadata": {},
165 | "outputs": [],
166 | "source": [
167 | "MODEL_PATH = os.path.join(tempfile.gettempdir(),\n",
168 | " \"iris_model_logistic_regression.pkl\")\n",
169 | "LABEL_PATH = os.path.join(tempfile.gettempdir(), \"iris_labels.json\")"
170 | ]
171 | },
172 | {
173 | "cell_type": "code",
174 | "execution_count": 9,
175 | "metadata": {},
176 | "outputs": [],
177 | "source": [
178 | "with open(MODEL_PATH, \"wb\") as f:\n",
179 | " pickle.dump(model, f)\n",
180 | "with open(LABEL_PATH, \"w\") as f:\n",
181 | " json.dump(target_names.tolist(), f)"
182 | ]
183 | },
184 | {
185 | "cell_type": "markdown",
186 | "metadata": {},
187 | "source": [
188 | "## Create a Deployment and Serve It\n",
189 | "\n",
190 | "Next, we define a servable model by instantiating a class and defining the `__call__` method that Ray Serve will use. "
191 | ]
192 | },
193 | {
194 | "cell_type": "code",
195 | "execution_count": 10,
196 | "metadata": {},
197 | "outputs": [],
198 | "source": [
199 | "@serve.deployment(route_prefix=\"/regressor\", num_replicas=2)\n",
200 | "class BoostingModel:\n",
201 | " def __init__(self):\n",
202 | " with open(MODEL_PATH, \"rb\") as f:\n",
203 | " self.model = pickle.load(f)\n",
204 | " with open(LABEL_PATH) as f:\n",
205 | " self.label_list = json.load(f)\n",
206 | "\n",
207 | " # async allows us to have this call concurrently \n",
208 | " async def __call__(self, starlette_request):\n",
209 | " payload = await starlette_request.json()\n",
210 | " print(\"Worker: received starlette request with data\", payload)\n",
211 | "\n",
212 | " input_vector = [\n",
213 | " payload[\"sepal length\"],\n",
214 | " payload[\"sepal width\"],\n",
215 | " payload[\"petal length\"],\n",
216 | " payload[\"petal width\"],\n",
217 | " ]\n",
218 | " prediction = self.model.predict([input_vector])[0]\n",
219 | " human_name = self.label_list[prediction]\n",
220 | " return {\"result\": human_name}"
221 | ]
222 | },
223 | {
224 | "cell_type": "markdown",
225 | "metadata": {},
226 | "source": [
227 | "## Deploy the model"
228 | ]
229 | },
230 | {
231 | "cell_type": "code",
232 | "execution_count": 11,
233 | "metadata": {},
234 | "outputs": [
235 | {
236 | "name": "stderr",
237 | "output_type": "stream",
238 | "text": [
239 | "2022-04-19 11:29:48,245\tINFO api.py:618 -- Updating deployment 'BoostingModel'. component=serve deployment=BoostingModel\n",
240 | "\u001b[2m\u001b[36m(ServeController pid=3675)\u001b[0m 2022-04-19 11:29:48,348\tINFO deployment_state.py:1210 -- Adding 2 replicas to deployment 'BoostingModel'. component=serve deployment=BoostingModel\n",
241 | "2022-04-19 11:29:50,252\tINFO api.py:633 -- Deployment 'BoostingModel' is ready at `http://127.0.0.1:8000/regressor`. component=serve deployment=BoostingModel\n"
242 | ]
243 | }
244 | ],
245 | "source": [
246 | "BoostingModel.deploy()"
247 | ]
248 | },
249 | {
250 | "cell_type": "markdown",
251 | "metadata": {},
252 | "source": [
253 | "## Score the model\n",
254 | "Internally, Serve stores the model as a Ray actor and routes traffic to it as the endpoint is queried, in this case over HTTP. \n",
255 | "\n",
256 | "Now let’s query the endpoint to see results."
257 | ]
258 | },
259 | {
260 | "cell_type": "code",
261 | "execution_count": 12,
262 | "metadata": {},
263 | "outputs": [],
264 | "source": [
265 | "sample_request_input = {\n",
266 | " \"sepal length\": 1.2,\n",
267 | " \"sepal width\": 1.0,\n",
268 | " \"petal length\": 1.1,\n",
269 | " \"petal width\": 0.9,\n",
270 | "}"
271 | ]
272 | },
273 | {
274 | "cell_type": "markdown",
275 | "metadata": {},
276 | "source": [
277 | "We can now send HTTP requests to our route `route_prefix=/regressor` at the default port 8000"
278 | ]
279 | },
280 | {
281 | "cell_type": "code",
282 | "execution_count": 13,
283 | "metadata": {},
284 | "outputs": [
285 | {
286 | "name": "stdout",
287 | "output_type": "stream",
288 | "text": [
289 | "{\n",
290 | " \"result\": \"versicolor\"\n",
291 | "}\n",
292 | "\u001b[2m\u001b[36m(BoostingModel pid=3679)\u001b[0m Worker: received starlette request with data {'sepal length': 1.2, 'sepal width': 1.0, 'petal length': 1.1, 'petal width': 0.9}\n"
293 | ]
294 | }
295 | ],
296 | "source": [
297 | "response = requests.get(\n",
298 | " \"http://localhost:8000/regressor\", json=sample_request_input)\n",
299 | "print(response.text)"
300 | ]
301 | },
302 | {
303 | "cell_type": "code",
304 | "execution_count": 14,
305 | "metadata": {},
306 | "outputs": [
307 | {
308 | "name": "stdout",
309 | "output_type": "stream",
310 | "text": [
311 | "{'result': 'versicolor'}\n",
312 | "\u001b[2m\u001b[36m(BoostingModel pid=3680)\u001b[0m Worker: received starlette request with data {'sepal length': 1.2, 'sepal width': 1.0, 'petal length': 1.1, 'petal width': 0.9}\n"
313 | ]
314 | }
315 | ],
316 | "source": [
317 | "response = requests.get(\"http://localhost:8000/regressor\", json=sample_request_input).json()\n",
318 | "print(response)"
319 | ]
320 | },
321 | {
322 | "cell_type": "code",
323 | "execution_count": 15,
324 | "metadata": {},
325 | "outputs": [
326 | {
327 | "name": "stdout",
328 | "output_type": "stream",
329 | "text": [
330 | "deployments: {'BoostingModel': Deployment(name=BoostingModel,version=None,route_prefix=/regressor)}\n"
331 | ]
332 | }
333 | ],
334 | "source": [
335 | "deployments = serve.list_deployments()\n",
336 | "print(f'deployments: {deployments}')"
337 | ]
338 | },
339 | {
340 | "cell_type": "code",
341 | "execution_count": 16,
342 | "metadata": {},
343 | "outputs": [
344 | {
345 | "name": "stderr",
346 | "output_type": "stream",
347 | "text": [
348 | "\u001b[2m\u001b[36m(ServeController pid=3675)\u001b[0m 2022-04-19 11:30:02,607\tINFO deployment_state.py:1236 -- Removing 2 replicas from deployment 'BoostingModel'. component=serve deployment=BoostingModel\n"
349 | ]
350 | }
351 | ],
352 | "source": [
353 | "serve.shutdown() "
354 | ]
355 | },
356 | {
357 | "cell_type": "markdown",
358 | "metadata": {},
359 | "source": [
360 | "### Exercise\n",
361 | "\n",
362 | "Here are some things you can try:\n",
363 | "\n",
364 | "1. Send more input requests."
365 | ]
366 | },
367 | {
368 | "cell_type": "markdown",
369 | "metadata": {},
370 | "source": [
371 | "## Homework\n",
372 | "1. Add a small model of your own and deploy it on Ray Serve\n",
373 | "2. Send some requests\n",
374 | "3. Try some [mini tutorials](https://docs.ray.io/en/latest/serve/tutorials/index.html) for other Frameworks"
375 | ]
376 | }
377 | ],
378 | "metadata": {
379 | "kernelspec": {
380 | "display_name": "Python 3 (ipykernel)",
381 | "language": "python",
382 | "name": "python3"
383 | },
384 | "language_info": {
385 | "codemirror_mode": {
386 | "name": "ipython",
387 | "version": 3
388 | },
389 | "file_extension": ".py",
390 | "mimetype": "text/x-python",
391 | "name": "python",
392 | "nbconvert_exporter": "python",
393 | "pygments_lexer": "ipython3",
394 | "version": "3.8.13"
395 | }
396 | },
397 | "nbformat": 4,
398 | "nbformat_minor": 4
399 | }
400 |
--------------------------------------------------------------------------------
/retired/highly_parallel.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "515dffba",
6 | "metadata": {},
7 | "source": [
8 | "# Using Ray for Highly Parallelizable Tasks\n",
9 | "\n",
10 | "While Ray can be used for very complex parallelization tasks,\n",
11 | "often we just want to do something simple in parallel.\n",
12 | "For example, we may have 100,000 time series to process with exactly the same algorithm,\n",
13 | "and each one takes a minute of processing.\n",
14 | "\n",
15 | "Clearly running it on a single processor is prohibitive: this would take 70 days.\n",
16 | "Even if we managed to use 8 processors on a single machine,\n",
17 | "that would bring it down to 9 days. But if we can use 8 machines, each with 16 cores,\n",
18 | "it can be done in about 12 hours.\n",
19 | "\n",
20 | "How can we use Ray for these types of task? \n",
21 | "\n",
22 | "## Let's try to compute the value of PI\n",
23 | "\n",
24 | "\n",
25 | "We take the simple example of computing the digits of pi using the [monte carlo](https://www.geeksforgeeks.org/estimating-value-pi-using-monte-carlo/) approach.\n",
26 | "The algorithm is simple: generate random x and y, and if ``x^2 + y^2 < 1``, it's\n",
27 | "inside the circle, we count as in. This actually turns out to be pi/4\n",
28 | "(remembering your high school math).\n",
29 | "\n",
30 | "
\n",
31 | "\n",
32 | "The following code (and this notebook) assumes you have already set up your Ray cluster and that you are running on the head node. For more details on how to set up a Ray cluster please see the [Ray Cluster Quickstart Guide](https://docs.ray.io/en/master/cluster/quickstart.html). \n",
33 | "\n",
34 | "📖 [Back to Table of Contents](../ex_00_tutorial_overview.ipynb)
\n",
35 | "\n"
36 | ]
37 | },
38 | {
39 | "cell_type": "code",
40 | "execution_count": 1,
41 | "id": "8e3e7c4f",
42 | "metadata": {},
43 | "outputs": [],
44 | "source": [
45 | "import os\n",
46 | "import time\n",
47 | "import logging\n",
48 | "from pprint import pprint\n",
49 | "\n",
50 | "import ray\n",
51 | "import random\n",
52 | "import math\n",
53 | "from fractions import Fraction"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": 2,
59 | "id": "92d2461b",
60 | "metadata": {
61 | "scrolled": true,
62 | "tags": [
63 | "remove-output"
64 | ]
65 | },
66 | "outputs": [
67 | {
68 | "data": {
69 | "text/html": [
70 | "\n",
71 | "
\n",
72 | "
Ray
\n",
73 | "
\n",
94 | "
\n",
95 | " \n",
96 | " Python version: | \n",
97 | " 3.8.13 | \n",
98 | "
\n",
99 | " \n",
100 | " Ray version: | \n",
101 | " 2.0.0 | \n",
102 | "
\n",
103 | " \n",
104 | " Dashboard: | \n",
105 | " http://127.0.0.1:8267 | \n",
106 | "
\n",
107 | "\n",
108 | "
\n",
109 | "
\n",
110 | "
\n"
111 | ],
112 | "text/plain": [
113 | "RayContext(dashboard_url='127.0.0.1:8267', python_version='3.8.13', ray_version='2.0.0', ray_commit='cba26cc83f6b5b8a2ff166594a65cb74c0ec8740', address_info={'node_ip_address': '127.0.0.1', 'raylet_ip_address': '127.0.0.1', 'redis_address': None, 'object_store_address': '/tmp/ray/session_2022-10-17_14-33-48_731138_54123/sockets/plasma_store', 'raylet_socket_name': '/tmp/ray/session_2022-10-17_14-33-48_731138_54123/sockets/raylet', 'webui_url': '127.0.0.1:8267', 'session_dir': '/tmp/ray/session_2022-10-17_14-33-48_731138_54123', 'metrics_export_port': 65012, 'gcs_address': '127.0.0.1:51188', 'address': '127.0.0.1:51188', 'dashboard_agent_listen_port': 52365, 'node_id': 'df1374dcddc8edce6f16014936802ab68042513e8fb82564d317abc4'})"
114 | ]
115 | },
116 | "execution_count": 2,
117 | "metadata": {},
118 | "output_type": "execute_result"
119 | }
120 | ],
121 | "source": [
122 | "if ray.is_initialized:\n",
123 | " ray.shutdown()\n",
124 | "ray.init(logging_level=logging.ERROR)"
125 | ]
126 | },
127 | {
128 | "cell_type": "markdown",
129 | "id": "b96f2eb9",
130 | "metadata": {},
131 | "source": [
132 | "We use the ``@ray.remote`` decorator to create a Ray task.\n",
133 | "A task is like a function, except the result is returned asynchronously.\n",
134 | "\n",
135 | "It also may not run on the local machine, it may run elsewhere in the cluster.\n",
136 | "This way you can run multiple tasks in parallel,\n",
137 | "beyond the limit of the number of processors you can have in a single machine."
138 | ]
139 | },
140 | {
141 | "cell_type": "code",
142 | "execution_count": 3,
143 | "id": "ece9887c",
144 | "metadata": {},
145 | "outputs": [],
146 | "source": [
147 | "@ray.remote\n",
148 | "def pi4_sample(sample_count):\n",
149 | " \"\"\"pi4_sample runs sample_count experiments, and returns the \n",
150 | " fraction of time it was inside the circle. \n",
151 | " \"\"\"\n",
152 | " in_count = 0\n",
153 | " for i in range(sample_count):\n",
154 | " x = random.random()\n",
155 | " y = random.random()\n",
156 | " if x*x + y*y <= 1:\n",
157 | " in_count += 1\n",
158 | " return Fraction(in_count, sample_count)\n"
159 | ]
160 | },
161 | {
162 | "cell_type": "markdown",
163 | "id": "05bf8675",
164 | "metadata": {},
165 | "source": [
166 | "To get the result of a future, we use `ray.get()` which \n",
167 | "blocks until the result is complete. "
168 | ]
169 | },
170 | {
171 | "cell_type": "code",
172 | "execution_count": 4,
173 | "id": "9d9a3509",
174 | "metadata": {},
175 | "outputs": [
176 | {
177 | "name": "stdout",
178 | "output_type": "stream",
179 | "text": [
180 | "Running 1000000 tests took 0.22035717964172363 seconds\n"
181 | ]
182 | }
183 | ],
184 | "source": [
185 | "SAMPLE_COUNT = 1000 * 1000\n",
186 | "start = time.time() \n",
187 | "future = pi4_sample.remote(sample_count = SAMPLE_COUNT)\n",
188 | "pi4 = ray.get(future)\n",
189 | "end = time.time()\n",
190 | "dur = end - start\n",
191 | "print(f'Running {SAMPLE_COUNT} tests took {dur} seconds')"
192 | ]
193 | },
194 | {
195 | "cell_type": "markdown",
196 | "id": "cc17429d",
197 | "metadata": {},
198 | "source": [
199 | "Now let's see how good our approximation is."
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": 5,
205 | "id": "42d4c464",
206 | "metadata": {},
207 | "outputs": [],
208 | "source": [
209 | "pi = pi4 * 4"
210 | ]
211 | },
212 | {
213 | "cell_type": "code",
214 | "execution_count": 6,
215 | "id": "4009bee0",
216 | "metadata": {},
217 | "outputs": [
218 | {
219 | "name": "stdout",
220 | "output_type": "stream",
221 | "text": [
222 | " Our computed PI: 3.138556; real PI: 3.141592653589793\n"
223 | ]
224 | }
225 | ],
226 | "source": [
227 | "print(f\" Our computed PI: {float(pi)}; real PI: {math.pi}\")"
228 | ]
229 | },
230 | {
231 | "cell_type": "code",
232 | "execution_count": 7,
233 | "id": "d19155d6",
234 | "metadata": {},
235 | "outputs": [
236 | {
237 | "data": {
238 | "text/plain": [
239 | "0.0009675320720080237"
240 | ]
241 | },
242 | "execution_count": 7,
243 | "metadata": {},
244 | "output_type": "execute_result"
245 | }
246 | ],
247 | "source": [
248 | "abs(pi-math.pi)/pi"
249 | ]
250 | },
251 | {
252 | "cell_type": "markdown",
253 | "id": "ddb3b095",
254 | "metadata": {},
255 | "source": [
256 | "Meh. A little off -- that's barely 4 decimal places.\n",
257 | "Why don't we do it a 100,000 times as much? Let's do 100 billion!\n",
258 | "`FULL_SAMPLE_COUNT = 100 * 1000 * 1000 * 1000 # 100 billion samples!` may take a while. \n",
259 | "\n",
260 | "Let's try with `1, 2 and 3b` and observe each value.\n"
261 | ]
262 | },
263 | {
264 | "cell_type": "code",
265 | "execution_count": 8,
266 | "id": "b7b9cff9",
267 | "metadata": {},
268 | "outputs": [
269 | {
270 | "name": "stdout",
271 | "output_type": "stream",
272 | "text": [
273 | "Doing 1000 batches\n",
274 | "Running 1000000 tests took 21.831931114196777 seconds\n"
275 | ]
276 | }
277 | ],
278 | "source": [
279 | "FULL_SAMPLE_COUNT = 1 * 1000 * 1000 * 1000 # 1 billion samples! \n",
280 | "start = time.time()\n",
281 | "BATCHES = int(FULL_SAMPLE_COUNT / SAMPLE_COUNT)\n",
282 | "print(f'Doing {BATCHES} batches')\n",
283 | "results = []\n",
284 | "for _ in range(BATCHES):\n",
285 | " results.append(pi4_sample.remote(sample_count = SAMPLE_COUNT))\n",
286 | "output = ray.get(results)\n",
287 | "end = time.time()\n",
288 | "dur = end - start\n",
289 | "print(f'Running {SAMPLE_COUNT} tests took {dur} seconds')"
290 | ]
291 | },
292 | {
293 | "cell_type": "markdown",
294 | "id": "94264de4",
295 | "metadata": {},
296 | "source": [
297 | "Notice that in the above, we generated a list with 100,000 futures.\n",
298 | "Now all we do is have to do is wait for the result.\n",
299 | "\n",
300 | "Depending on your ray cluster's size, this might take a few minutes.\n",
301 | "But to give you some idea, if we were to do it on a single machine,\n",
302 | "when we ran this, it took 0.4 seconds.\n",
303 | "\n",
304 | "On a single core, that means we're looking at 0.4 * 100000 = about 11 hours. \n",
305 | "\n",
306 | "So now, rather than just a single core working on this, we have all our cores working on the task together (depending on the number cores on each worker node). "
307 | ]
308 | },
309 | {
310 | "cell_type": "code",
311 | "execution_count": 9,
312 | "id": "76eba02d",
313 | "metadata": {},
314 | "outputs": [],
315 | "source": [
316 | "pi = sum(output)*4/len(output)"
317 | ]
318 | },
319 | {
320 | "cell_type": "code",
321 | "execution_count": 10,
322 | "id": "ede2bd8c",
323 | "metadata": {},
324 | "outputs": [
325 | {
326 | "data": {
327 | "text/plain": [
328 | "3.14151778"
329 | ]
330 | },
331 | "execution_count": 10,
332 | "metadata": {},
333 | "output_type": "execute_result"
334 | }
335 | ],
336 | "source": [
337 | "float(pi)"
338 | ]
339 | },
340 | {
341 | "cell_type": "code",
342 | "execution_count": 11,
343 | "id": "bb62cb27",
344 | "metadata": {},
345 | "outputs": [
346 | {
347 | "data": {
348 | "text/plain": [
349 | "2.3833571870816713e-05"
350 | ]
351 | },
352 | "execution_count": 11,
353 | "metadata": {},
354 | "output_type": "execute_result"
355 | }
356 | ],
357 | "source": [
358 | "float(abs(pi-math.pi)/pi)"
359 | ]
360 | },
361 | {
362 | "cell_type": "markdown",
363 | "id": "30d12e50",
364 | "metadata": {},
365 | "source": [
366 | "Not bad at all -- we're off by a millionth. "
367 | ]
368 | },
369 | {
370 | "cell_type": "markdown",
371 | "id": "f038accd-21f7-499a-a2aa-40aad28a03db",
372 | "metadata": {},
373 | "source": [
374 | "### Reference\n",
375 | "\n",
376 | "1. [How to scale Python multiprocessing to a cluster with one line of code](https://medium.com/distributed-computing-with-ray/how-to-scale-python-multiprocessing-to-a-cluster-with-one-line-of-code-d19f242f60ff) \n",
377 | "2. [Using Ray for Highly Parallelizable Tasks](https://docs.ray.io/en/master/ray-core/examples/highly_parallel.html)"
378 | ]
379 | },
380 | {
381 | "cell_type": "markdown",
382 | "id": "ea4b1786-3940-41e5-8460-190b51c6837c",
383 | "metadata": {},
384 | "source": [
385 | "📖 [Back to Table of Contents](../ex_00_tutorial_overview.ipynb)
"
386 | ]
387 | }
388 | ],
389 | "metadata": {
390 | "celltoolbar": "Tags",
391 | "kernelspec": {
392 | "display_name": "Python 3 (ipykernel)",
393 | "language": "python",
394 | "name": "python3"
395 | },
396 | "language_info": {
397 | "codemirror_mode": {
398 | "name": "ipython",
399 | "version": 3
400 | },
401 | "file_extension": ".py",
402 | "mimetype": "text/x-python",
403 | "name": "python",
404 | "nbconvert_exporter": "python",
405 | "pygments_lexer": "ipython3",
406 | "version": "3.8.13"
407 | }
408 | },
409 | "nbformat": 4,
410 | "nbformat_minor": 5
411 | }
412 |
--------------------------------------------------------------------------------
/retired/images/PatternsMLProduction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/PatternsMLProduction.png
--------------------------------------------------------------------------------
/retired/images/PyCon2022_Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/PyCon2022_Logo.png
--------------------------------------------------------------------------------
/retired/images/actor_and_workders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/actor_and_workders.png
--------------------------------------------------------------------------------
/retired/images/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/architecture.png
--------------------------------------------------------------------------------
/retired/images/func_class_deployment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/func_class_deployment.png
--------------------------------------------------------------------------------
/retired/images/func_class_deployment_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/func_class_deployment_2.png
--------------------------------------------------------------------------------
/retired/images/object_resolution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/object_resolution.png
--------------------------------------------------------------------------------
/retired/images/ray-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/ray-logo.png
--------------------------------------------------------------------------------
/retired/images/ray_basic_patterns.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/ray_basic_patterns.png
--------------------------------------------------------------------------------
/retired/images/ray_cluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/ray_cluster.png
--------------------------------------------------------------------------------
/retired/images/ray_serve_deployment_workflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/ray_serve_deployment_workflow.png
--------------------------------------------------------------------------------
/retired/images/ray_serve_overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/ray_serve_overview.png
--------------------------------------------------------------------------------
/retired/images/ray_tune_dist_hpo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/ray_tune_dist_hpo.png
--------------------------------------------------------------------------------
/retired/images/ray_worker_actor_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/ray_worker_actor_1.png
--------------------------------------------------------------------------------
/retired/images/ray_worker_actor_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/ray_worker_actor_2.png
--------------------------------------------------------------------------------
/retired/images/sentiment_analysis.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/sentiment_analysis.jpeg
--------------------------------------------------------------------------------
/retired/images/shared_memory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/shared_memory.png
--------------------------------------------------------------------------------
/retired/images/shared_memory_plasma_store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/shared_memory_plasma_store.png
--------------------------------------------------------------------------------
/retired/images/task_api_add_array.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/task_api_add_array.png
--------------------------------------------------------------------------------
/retired/images/task_dependencies_graphs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/task_dependencies_graphs.png
--------------------------------------------------------------------------------
/retired/images/task_ownership.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/task_ownership.png
--------------------------------------------------------------------------------
/retired/images/tune_flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/images/tune_flow.png
--------------------------------------------------------------------------------
/retired/requirements.txt:
--------------------------------------------------------------------------------
1 | ray[default]
2 | ray[all]
3 | jupyter
4 | jupyterlab
5 | scikit-learn
6 | tune-sklearn
7 | xgboost
8 | xgboost-ray
9 | tqdm
10 |
--------------------------------------------------------------------------------
/retired/slides/pyconus2022/pyconsus_slides.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/slides/pyconus2022/pyconsus_slides.pdf
--------------------------------------------------------------------------------
/retired/slides/weekly-demos/presentation_slides.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/retired/slides/weekly-demos/presentation_slides.pdf
--------------------------------------------------------------------------------
/retired/solutions/ex_01_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 23,
6 | "id": "db1a7d02-4378-4184-bd08-d29c7ae8d8ab",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "import math\n",
11 | "import numpy as np\n",
12 | "import logging\n",
13 | "from pprint import pprint\n",
14 | "from typing import List\n",
15 | "import ray"
16 | ]
17 | },
18 | {
19 | "cell_type": "code",
20 | "execution_count": 25,
21 | "id": "b4ef2d84-4903-429e-96c8-a24210ceec34",
22 | "metadata": {},
23 | "outputs": [],
24 | "source": [
25 | "@ray.remote\n",
26 | "def slow_method(num: int, dims=10) -> List[np.array]:\n",
27 | " dot_products = []\n",
28 | " for _ in range(num):\n",
29 | " # Create a dims x dims matrix\n",
30 | " x = np.random.rand(dims, dims)\n",
31 | " y = np.random.rand(dims, dims)\n",
32 | " # Create a dot product of itself\n",
33 | " dot_products.append(np.dot(x, y))\n",
34 | " return dot_products"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": 26,
40 | "id": "68e43170-0260-4f7b-91df-4433770145a2",
41 | "metadata": {},
42 | "outputs": [
43 | {
44 | "name": "stdout",
45 | "output_type": "stream",
46 | "text": [
47 | "RayContext(dashboard_url='127.0.0.1:8268', python_version='3.8.12', ray_version='2.0.0.dev0', ray_commit='{{RAY_COMMIT_SHA}}', address_info={'node_ip_address': '127.0.0.1', 'raylet_ip_address': '127.0.0.1', 'redis_address': None, 'object_store_address': '/tmp/ray/session_2022-04-12_20-08-32_792180_75624/sockets/plasma_store', 'raylet_socket_name': '/tmp/ray/session_2022-04-12_20-08-32_792180_75624/sockets/raylet', 'webui_url': '127.0.0.1:8268', 'session_dir': '/tmp/ray/session_2022-04-12_20-08-32_792180_75624', 'metrics_export_port': 63718, 'gcs_address': '127.0.0.1:61890', 'address': '127.0.0.1:61890', 'node_id': '1033c5f86275a3c136446d6f0167df4252ea2bcb1d8e624731d0683f'})\n"
48 | ]
49 | }
50 | ],
51 | "source": [
52 | "if ray.is_initialized:\n",
53 | " ray.shutdown()\n",
54 | "context = ray.init(logging_level=logging.ERROR)\n",
55 | "pprint(context)"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": 27,
61 | "id": "129f5c00-b71b-45d8-84ca-25b20ff1acc9",
62 | "metadata": {},
63 | "outputs": [
64 | {
65 | "name": "stdout",
66 | "output_type": "stream",
67 | "text": [
68 | "Dashboard url: http://127.0.0.1:8268\n"
69 | ]
70 | }
71 | ],
72 | "source": [
73 | "print(f\"Dashboard url: http://{context.address_info['webui_url']}\")"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": 28,
79 | "id": "f0677e24-0b30-4831-b348-2ce8147576a8",
80 | "metadata": {},
81 | "outputs": [
82 | {
83 | "name": "stdout",
84 | "output_type": "stream",
85 | "text": [
86 | "[[], [array([[1254.75103542, 1263.44977541, 1256.79552605, ..., 1251.38925517,\n",
87 | " 1258.10691228, 1237.67227246],\n",
88 | " [1237.92135129, 1248.11874766, 1236.71503673, ..., 1235.37863989,\n",
89 | " 1235.01688414, 1231.5786307 ],\n",
90 | " [1242.27804496, 1254.59332238, 1258.56410395, ..., 1246.62994948,\n",
91 | " 1241.00129843, 1241.24246935],\n",
92 | " ...,\n",
93 | " [1250.81478881, 1250.75241626, 1254.67709941, ..., 1244.01105921,\n",
94 | " 1250.12977093, 1239.15314547],\n",
95 | " [1245.00991477, 1252.6484969 , 1245.82516085, ..., 1255.55391927,\n",
96 | " 1251.72045296, 1231.17696796],\n",
97 | " [1244.15661435, 1248.75711711, 1247.04815943, ..., 1252.2612197 ,\n",
98 | " 1245.36061293, 1235.65127128]])], [array([[1265.35240908, 1238.13943797, 1260.19433701, ..., 1265.17357757,\n",
99 | " 1262.3145888 , 1247.57462287],\n",
100 | " [1263.34239507, 1230.35471309, 1255.92384506, ..., 1264.9407517 ,\n",
101 | " 1261.53195768, 1241.07058822],\n",
102 | " [1275.19653919, 1238.78333325, 1261.78395583, ..., 1274.36457588,\n",
103 | " 1273.23073055, 1264.31254573],\n",
104 | " ...,\n",
105 | " [1262.18269999, 1241.02203374, 1258.06179841, ..., 1273.52002282,\n",
106 | " 1275.60597867, 1255.66137056],\n",
107 | " [1260.24715633, 1237.42101072, 1255.94604066, ..., 1266.85549001,\n",
108 | " 1277.48965259, 1256.82917975],\n",
109 | " [1265.67630923, 1235.74650174, 1259.83534502, ..., 1262.03897968,\n",
110 | " 1270.29616271, 1261.32694735]]), array([[1229.22745053, 1223.14769839, 1226.62380873, ..., 1232.92573491,\n",
111 | " 1230.67784599, 1219.97675392],\n",
112 | " [1251.1204877 , 1244.92510887, 1258.29774573, ..., 1254.08602637,\n",
113 | " 1256.86271346, 1251.21357563],\n",
114 | " [1245.68406865, 1252.6341574 , 1252.64961243, ..., 1259.25714296,\n",
115 | " 1256.8215843 , 1253.42041772],\n",
116 | " ...,\n",
117 | " [1254.04990316, 1260.925521 , 1260.89802286, ..., 1254.57811256,\n",
118 | " 1268.28828872, 1251.87933366],\n",
119 | " [1249.85371277, 1258.6821871 , 1257.09990314, ..., 1257.83661774,\n",
120 | " 1253.46782481, 1251.61481129],\n",
121 | " [1235.28848775, 1254.88757995, 1249.20652425, ..., 1247.39977529,\n",
122 | " 1252.95532462, 1246.12850938]])], [array([[1237.81034962, 1236.3385498 , 1260.74293891, ..., 1247.40732119,\n",
123 | " 1255.49019786, 1234.65009041],\n",
124 | " [1229.37379583, 1235.26155242, 1260.19967546, ..., 1239.2240627 ,\n",
125 | " 1268.39229399, 1262.30085441],\n",
126 | " [1212.49330006, 1217.49904466, 1252.89927136, ..., 1229.37853306,\n",
127 | " 1244.18497365, 1240.58291376],\n",
128 | " ...,\n",
129 | " [1232.89610271, 1231.5279054 , 1250.30524808, ..., 1248.25738456,\n",
130 | " 1241.57469297, 1248.94433893],\n",
131 | " [1220.17199049, 1235.9151727 , 1242.50240349, ..., 1239.02820681,\n",
132 | " 1254.14673226, 1241.34966448],\n",
133 | " [1232.70927738, 1242.47638247, 1260.38366213, ..., 1247.5327304 ,\n",
134 | " 1253.41925295, 1238.355636 ]]), array([[1226.83538398, 1250.75981244, 1236.05107696, ..., 1247.02754745,\n",
135 | " 1231.40437062, 1244.92371953],\n",
136 | " [1258.40937714, 1272.51123025, 1252.82918253, ..., 1265.44719233,\n",
137 | " 1232.02523032, 1251.31376379],\n",
138 | " [1244.96201065, 1265.26518192, 1237.18163867, ..., 1263.00783624,\n",
139 | " 1225.16045311, 1240.55973161],\n",
140 | " ...,\n",
141 | " [1250.79654007, 1276.72216528, 1245.1201029 , ..., 1278.40894695,\n",
142 | " 1249.17225512, 1256.80243346],\n",
143 | " [1249.05748426, 1270.8616783 , 1255.78497467, ..., 1261.89291726,\n",
144 | " 1260.94865019, 1259.39621987],\n",
145 | " [1257.59053357, 1281.27654146, 1249.44735705, ..., 1268.83853469,\n",
146 | " 1257.13456118, 1262.57993856]]), array([[1229.93581334, 1238.68192502, 1258.34499983, ..., 1236.90671756,\n",
147 | " 1241.18945337, 1242.23559996],\n",
148 | " [1222.70315868, 1239.62586206, 1246.9114698 , ..., 1235.11449119,\n",
149 | " 1251.9476294 , 1252.99861152],\n",
150 | " [1228.61173964, 1242.01697267, 1244.62706445, ..., 1240.98082085,\n",
151 | " 1249.6202127 , 1252.63595589],\n",
152 | " ...,\n",
153 | " [1219.70236538, 1238.10175191, 1239.6367322 , ..., 1240.79453755,\n",
154 | " 1251.8095576 , 1227.20463102],\n",
155 | " [1222.6439827 , 1234.86651298, 1257.16306799, ..., 1242.23659314,\n",
156 | " 1242.93048293, 1235.69568988],\n",
157 | " [1222.7861455 , 1241.36383562, 1260.20458976, ..., 1251.66379778,\n",
158 | " 1248.41131281, 1255.0706066 ]])], [array([[1251.62149823, 1249.00449431, 1263.50573124, ..., 1244.21264619,\n",
159 | " 1239.0390246 , 1236.7053611 ],\n",
160 | " [1245.57837855, 1244.79946345, 1258.69885503, ..., 1242.04519921,\n",
161 | " 1239.13914121, 1239.61493992],\n",
162 | " [1237.61988111, 1245.1007778 , 1261.93142022, ..., 1242.47064323,\n",
163 | " 1231.03100103, 1248.55148331],\n",
164 | " ...,\n",
165 | " [1243.81735599, 1249.94747723, 1260.21732 , ..., 1241.40081698,\n",
166 | " 1248.69097974, 1240.13447004],\n",
167 | " [1274.35303655, 1267.98866352, 1288.06443476, ..., 1276.00058952,\n",
168 | " 1265.98152515, 1276.42032526],\n",
169 | " [1267.90271971, 1258.74824338, 1268.90363668, ..., 1255.85413356,\n",
170 | " 1258.59144098, 1252.36828253]]), array([[1261.28822632, 1240.3416569 , 1261.89785174, ..., 1245.55910059,\n",
171 | " 1251.55885247, 1244.89516814],\n",
172 | " [1276.89438538, 1250.09239874, 1247.12087337, ..., 1279.07614608,\n",
173 | " 1262.62822709, 1262.19425857],\n",
174 | " [1258.71420113, 1243.24408893, 1247.10858221, ..., 1233.31830443,\n",
175 | " 1243.51915924, 1239.52189042],\n",
176 | " ...,\n",
177 | " [1259.39530084, 1231.71529341, 1240.88957964, ..., 1249.01096399,\n",
178 | " 1246.92752435, 1241.15721588],\n",
179 | " [1262.34023928, 1231.08472549, 1261.56620681, ..., 1235.93251394,\n",
180 | " 1252.83088782, 1249.20858187],\n",
181 | " [1239.05052215, 1235.18820102, 1246.50081769, ..., 1247.07231645,\n",
182 | " 1235.82086781, 1247.3694316 ]]), array([[1260.14709582, 1267.18327581, 1246.71322653, ..., 1276.29536668,\n",
183 | " 1280.28962292, 1260.27166042],\n",
184 | " [1257.431675 , 1255.95930161, 1237.45866183, ..., 1265.49199407,\n",
185 | " 1277.46097709, 1238.87044391],\n",
186 | " [1233.02760804, 1252.14700152, 1217.54964254, ..., 1261.39846519,\n",
187 | " 1268.21000353, 1233.58291328],\n",
188 | " ...,\n",
189 | " [1251.06464901, 1269.66823614, 1236.9061452 , ..., 1262.40237022,\n",
190 | " 1282.56864003, 1240.21228025],\n",
191 | " [1259.17476265, 1249.66548547, 1238.30847497, ..., 1259.49753889,\n",
192 | " 1287.22700655, 1237.32907333],\n",
193 | " [1231.35980777, 1249.22499092, 1238.91392114, ..., 1260.06259597,\n",
194 | " 1270.66406536, 1241.72662082]]), array([[1251.14599571, 1273.99782941, 1232.81183743, ..., 1268.77330799,\n",
195 | " 1243.84342157, 1262.55539061],\n",
196 | " [1272.78271412, 1282.10416011, 1256.05547558, ..., 1270.3257063 ,\n",
197 | " 1239.15703595, 1275.77170289],\n",
198 | " [1250.69543524, 1258.36706144, 1226.5822154 , ..., 1258.85378613,\n",
199 | " 1233.21871841, 1256.89631698],\n",
200 | " ...,\n",
201 | " [1229.19730682, 1255.42920859, 1224.8175728 , ..., 1250.75877617,\n",
202 | " 1206.08590619, 1242.75695134],\n",
203 | " [1243.29506617, 1253.09376636, 1228.78481077, ..., 1258.79886183,\n",
204 | " 1227.27296674, 1247.31968855],\n",
205 | " [1260.09013668, 1267.79411824, 1237.81273515, ..., 1257.9850232 ,\n",
206 | " 1236.73389906, 1267.71889264]])]]\n",
207 | "CPU times: user 151 ms, sys: 71.1 ms, total: 222 ms\n",
208 | "Wall time: 22.2 s\n"
209 | ]
210 | }
211 | ],
212 | "source": [
213 | "%%time\n",
214 | "results = [slow_method.remote(i, 5_000) for i in range(5)]\n",
215 | "print(ray.get(results))"
216 | ]
217 | },
218 | {
219 | "cell_type": "code",
220 | "execution_count": 29,
221 | "id": "8482dfac-4043-410c-a75d-1588cfd893c7",
222 | "metadata": {},
223 | "outputs": [],
224 | "source": [
225 | "ray.shutdown()"
226 | ]
227 | }
228 | ],
229 | "metadata": {
230 | "kernelspec": {
231 | "display_name": "Python 3 (ipykernel)",
232 | "language": "python",
233 | "name": "python3"
234 | },
235 | "language_info": {
236 | "codemirror_mode": {
237 | "name": "ipython",
238 | "version": 3
239 | },
240 | "file_extension": ".py",
241 | "mimetype": "text/x-python",
242 | "name": "python",
243 | "nbconvert_exporter": "python",
244 | "pygments_lexer": "ipython3",
245 | "version": "3.8.12"
246 | }
247 | },
248 | "nbformat": 4,
249 | "nbformat_minor": 5
250 | }
251 |
--------------------------------------------------------------------------------
/retired/solutions/ex_02_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "id": "1be69dae-83d9-43d1-81e7-41c26b683ce3",
7 | "metadata": {},
8 | "outputs": [
9 | {
10 | "name": "stdout",
11 | "output_type": "stream",
12 | "text": [
13 | "RayContext(dashboard_url='127.0.0.1:8267', python_version='3.8.12', ray_version='2.0.0.dev0', ray_commit='{{RAY_COMMIT_SHA}}', address_info={'node_ip_address': '127.0.0.1', 'raylet_ip_address': '127.0.0.1', 'redis_address': None, 'object_store_address': '/tmp/ray/session_2022-04-12_19-26-55_484801_74445/sockets/plasma_store', 'raylet_socket_name': '/tmp/ray/session_2022-04-12_19-26-55_484801_74445/sockets/raylet', 'webui_url': '127.0.0.1:8267', 'session_dir': '/tmp/ray/session_2022-04-12_19-26-55_484801_74445', 'metrics_export_port': 65382, 'gcs_address': '127.0.0.1:64612', 'address': '127.0.0.1:64612', 'node_id': '7232289a9b1cd1025eca11df0e1122621f1a665ea41c197b9d9d35c0'})\n"
14 | ]
15 | }
16 | ],
17 | "source": [
18 | "import logging\n",
19 | "from pprint import pprint\n",
20 | "import ray\n",
21 | "\n",
22 | "if ray.is_initialized:\n",
23 | " ray.shutdown()\n",
24 | "context = ray.init(logging_level=logging.ERROR)\n",
25 | "pprint(context)"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": 2,
31 | "id": "0084eab3-f381-430d-a750-74b4a8e434f8",
32 | "metadata": {},
33 | "outputs": [
34 | {
35 | "name": "stdout",
36 | "output_type": "stream",
37 | "text": [
38 | "Dashboard url: http://127.0.0.1:8267\n"
39 | ]
40 | }
41 | ],
42 | "source": [
43 | "print(f\"Dashboard url: http://{context.address_info['webui_url']}\")"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": 6,
49 | "id": "8110da95-01b2-4b73-ba13-f7cfea166329",
50 | "metadata": {},
51 | "outputs": [],
52 | "source": [
53 | "@ray.remote\n",
54 | "def my_function (num_list):\n",
55 | " return sum(num_list)"
56 | ]
57 | },
58 | {
59 | "cell_type": "markdown",
60 | "id": "7bf709bd-217c-4553-80c1-042c7dddb34f",
61 | "metadata": {},
62 | "source": [
63 | "### Method 1\n",
64 | "\n",
65 | "Without comprehension"
66 | ]
67 | },
68 | {
69 | "cell_type": "code",
70 | "execution_count": 11,
71 | "id": "7618f6df-f2b6-4286-9dae-fe24497caae0",
72 | "metadata": {},
73 | "outputs": [
74 | {
75 | "data": {
76 | "text/plain": [
77 | "[ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000015000000),\n",
78 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000016000000),\n",
79 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000017000000),\n",
80 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000018000000),\n",
81 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000019000000),\n",
82 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001a000000),\n",
83 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001b000000),\n",
84 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001c000000),\n",
85 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001d000000),\n",
86 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001e000000)]"
87 | ]
88 | },
89 | "execution_count": 11,
90 | "metadata": {},
91 | "output_type": "execute_result"
92 | }
93 | ],
94 | "source": [
95 | "obj_refs = [ray.put(i) for i in range(10)]\n",
96 | "obj_refs"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": 13,
102 | "id": "6835d594-e51d-4da8-a53c-01d7d6c39e44",
103 | "metadata": {},
104 | "outputs": [
105 | {
106 | "data": {
107 | "text/plain": [
108 | "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
109 | ]
110 | },
111 | "execution_count": 13,
112 | "metadata": {},
113 | "output_type": "execute_result"
114 | }
115 | ],
116 | "source": [
117 | "values = ray.get(obj_refs)\n",
118 | "values"
119 | ]
120 | },
121 | {
122 | "cell_type": "code",
123 | "execution_count": 14,
124 | "id": "4a48c181-a6c8-41fe-bf71-78ceaaff2fef",
125 | "metadata": {},
126 | "outputs": [],
127 | "source": [
128 | "sum_obj_ref = my_function.remote(values)"
129 | ]
130 | },
131 | {
132 | "cell_type": "code",
133 | "execution_count": 15,
134 | "id": "3ec83055-db03-4651-959b-26d116905ea5",
135 | "metadata": {},
136 | "outputs": [
137 | {
138 | "data": {
139 | "text/plain": [
140 | "45"
141 | ]
142 | },
143 | "execution_count": 15,
144 | "metadata": {},
145 | "output_type": "execute_result"
146 | }
147 | ],
148 | "source": [
149 | "ray.get(sum_obj_ref)"
150 | ]
151 | },
152 | {
153 | "cell_type": "markdown",
154 | "id": "85096fa6-8cea-4b50-aff7-3b4857df64ec",
155 | "metadata": {},
156 | "source": [
157 | "### Method 2\n",
158 | "Using comprehension"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 16,
164 | "id": "33f2a5d0-ea98-4997-9cde-c3cf7d801f85",
165 | "metadata": {},
166 | "outputs": [
167 | {
168 | "data": {
169 | "text/plain": [
170 | "45"
171 | ]
172 | },
173 | "execution_count": 16,
174 | "metadata": {},
175 | "output_type": "execute_result"
176 | }
177 | ],
178 | "source": [
179 | "ray.get(my_function.remote(ray.get([ray.put(i) for i in range(10)])))"
180 | ]
181 | }
182 | ],
183 | "metadata": {
184 | "kernelspec": {
185 | "display_name": "Python 3 (ipykernel)",
186 | "language": "python",
187 | "name": "python3"
188 | },
189 | "language_info": {
190 | "codemirror_mode": {
191 | "name": "ipython",
192 | "version": 3
193 | },
194 | "file_extension": ".py",
195 | "mimetype": "text/x-python",
196 | "name": "python",
197 | "nbconvert_exporter": "python",
198 | "pygments_lexer": "ipython3",
199 | "version": "3.8.12"
200 | }
201 | },
202 | "nbformat": 4,
203 | "nbformat_minor": 5
204 | }
205 |
--------------------------------------------------------------------------------
/retired/solutions/ex_03_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 2,
6 | "id": "e425ccaf-273b-4126-8b2b-147dbbd8aa8a",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "import logging\n",
11 | "import time\n",
12 | "from pprint import pprint\n",
13 | "import ray\n",
14 | "import random\n",
15 | "from random import randint\n",
16 | "import numpy as np"
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": 3,
22 | "id": "2f61c376-5c2f-4f26-bd57-1b50624dadbd",
23 | "metadata": {},
24 | "outputs": [],
25 | "source": [
26 | "from collections import defaultdict\n",
27 | "@ray.remote\n",
28 | "class LoggingActor(object):\n",
29 | " def __init__(self):\n",
30 | " self.logs = defaultdict(list)\n",
31 | " \n",
32 | " def log(self, index, message):\n",
33 | " self.logs[index].append(message)\n",
34 | " \n",
35 | " def get_logs(self):\n",
36 | " return dict(self.logs)\n",
37 | " \n",
38 | "@ray.remote\n",
39 | "def run_experiment(experiment_index, logging_actor):\n",
40 | " for i in range(60):\n",
41 | " time.sleep(1)\n",
42 | " # Push a logging message to the actor.\n",
43 | " logging_actor.log.remote(experiment_index, 'On iteration {}'.format(i)) "
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": 4,
49 | "id": "566abe08-0af6-42e7-ba57-532166f4d0ce",
50 | "metadata": {},
51 | "outputs": [
52 | {
53 | "name": "stdout",
54 | "output_type": "stream",
55 | "text": [
56 | "RayContext(dashboard_url='127.0.0.1:8265', python_version='3.8.12', ray_version='2.0.0.dev0', ray_commit='{{RAY_COMMIT_SHA}}', address_info={'node_ip_address': '127.0.0.1', 'raylet_ip_address': '127.0.0.1', 'redis_address': None, 'object_store_address': '/tmp/ray/session_2022-04-12_17-36-24_075332_63548/sockets/plasma_store', 'raylet_socket_name': '/tmp/ray/session_2022-04-12_17-36-24_075332_63548/sockets/raylet', 'webui_url': '127.0.0.1:8265', 'session_dir': '/tmp/ray/session_2022-04-12_17-36-24_075332_63548', 'metrics_export_port': 55021, 'gcs_address': '127.0.0.1:63184', 'address': '127.0.0.1:63184', 'node_id': '7b1932893136ebdc505d7c89756e53dd861ab5a948a3831d403f163e'})\n"
57 | ]
58 | }
59 | ],
60 | "source": [
61 | "if ray.is_initialized:\n",
62 | " ray.shutdown()\n",
63 | "context = ray.init(logging_level=logging.ERROR)\n",
64 | "pprint(context)"
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": 5,
70 | "id": "cd2a3f51-92a1-4ff9-8d22-56b47ebf69da",
71 | "metadata": {},
72 | "outputs": [],
73 | "source": [
74 | "logging_actor = LoggingActor.remote()\n",
75 | "experiment_ids = []\n",
76 | "for i in range(3):\n",
77 | " experiment_ids.append(run_experiment.remote(i, logging_actor))"
78 | ]
79 | },
80 | {
81 | "cell_type": "code",
82 | "execution_count": 7,
83 | "id": "3ed4fc03-339f-4866-a3ef-dfd12051d078",
84 | "metadata": {},
85 | "outputs": [
86 | {
87 | "name": "stdout",
88 | "output_type": "stream",
89 | "text": [
90 | "{0: ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8', 'On iteration 9', 'On iteration 10', 'On iteration 11', 'On iteration 12', 'On iteration 13', 'On iteration 14', 'On iteration 15', 'On iteration 16', 'On iteration 17', 'On iteration 18', 'On iteration 19', 'On iteration 20', 'On iteration 21', 'On iteration 22', 'On iteration 23', 'On iteration 24', 'On iteration 25', 'On iteration 26', 'On iteration 27', 'On iteration 28', 'On iteration 29', 'On iteration 30', 'On iteration 31', 'On iteration 32', 'On iteration 33'], 2: ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8', 'On iteration 9', 'On iteration 10', 'On iteration 11', 'On iteration 12', 'On iteration 13', 'On iteration 14', 'On iteration 15', 'On iteration 16', 'On iteration 17', 'On iteration 18', 'On iteration 19', 'On iteration 20', 'On iteration 21', 'On iteration 22', 'On iteration 23', 'On iteration 24', 'On iteration 25', 'On iteration 26', 'On iteration 27', 'On iteration 28', 'On iteration 29', 'On iteration 30', 'On iteration 31', 'On iteration 32', 'On iteration 33'], 1: ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8', 'On iteration 9', 'On iteration 10', 'On iteration 11', 'On iteration 12', 'On iteration 13', 'On iteration 14', 'On iteration 15', 'On iteration 16', 'On iteration 17', 'On iteration 18', 'On iteration 19', 'On iteration 20', 'On iteration 21', 'On iteration 22', 'On iteration 23', 'On iteration 24', 'On iteration 25', 'On iteration 26', 'On iteration 27', 'On iteration 28', 'On iteration 29', 'On iteration 30', 'On iteration 31', 'On iteration 32', 'On iteration 33']}\n"
91 | ]
92 | }
93 | ],
94 | "source": [
95 | "logs = logging_actor.get_logs.remote()\n",
96 | "print(ray.get(logs))"
97 | ]
98 | }
99 | ],
100 | "metadata": {
101 | "kernelspec": {
102 | "display_name": "Python 3 (ipykernel)",
103 | "language": "python",
104 | "name": "python3"
105 | },
106 | "language_info": {
107 | "codemirror_mode": {
108 | "name": "ipython",
109 | "version": 3
110 | },
111 | "file_extension": ".py",
112 | "mimetype": "text/x-python",
113 | "name": "python",
114 | "nbconvert_exporter": "python",
115 | "pygments_lexer": "ipython3",
116 | "version": "3.8.12"
117 | }
118 | },
119 | "nbformat": 4,
120 | "nbformat_minor": 5
121 | }
122 |
--------------------------------------------------------------------------------
/retired/solutions/ex_08_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "id": "fbd3efe1-5183-4393-91ad-566aaddee191",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "import ray\n",
11 | "from ray import serve\n",
12 | "import random\n",
13 | "\n",
14 | "import requests"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 2,
20 | "id": "f717b5af-3ee4-4d35-96ea-5ea8be26470e",
21 | "metadata": {},
22 | "outputs": [
23 | {
24 | "name": "stderr",
25 | "output_type": "stream",
26 | "text": [
27 | "2022-04-12 18:56:04,726\tINFO services.py:1460 -- View the Ray dashboard at \u001b[1m\u001b[32mhttp://127.0.0.1:8266\u001b[39m\u001b[22m\n",
28 | "\u001b[2m\u001b[36m(ServeController pid=71592)\u001b[0m 2022-04-12 18:56:08,436\tINFO checkpoint_path.py:15 -- Using RayInternalKVStore for controller checkpoint and recovery.\n",
29 | "\u001b[2m\u001b[36m(ServeController pid=71592)\u001b[0m 2022-04-12 18:56:08,544\tINFO http_state.py:106 -- Starting HTTP proxy with name 'SERVE_CONTROLLER_ACTOR:ziytnj:SERVE_PROXY_ACTOR-node:127.0.0.1-0' on node 'node:127.0.0.1-0' listening on '127.0.0.1:8000'\n",
30 | "2022-04-12 18:56:09,786\tINFO api.py:797 -- Started Serve instance in namespace 'serve'.\n"
31 | ]
32 | },
33 | {
34 | "data": {
35 | "text/plain": [
36 | ""
37 | ]
38 | },
39 | "execution_count": 2,
40 | "metadata": {},
41 | "output_type": "execute_result"
42 | }
43 | ],
44 | "source": [
45 | "serve.start()"
46 | ]
47 | },
48 | {
49 | "cell_type": "markdown",
50 | "id": "55dff614-a30a-44d0-842b-a24e196450a1",
51 | "metadata": {},
52 | "source": [
53 | "### Create a Python function deployment "
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": 3,
59 | "id": "9e8cd218-a831-4e12-b89a-46f878e46b97",
60 | "metadata": {},
61 | "outputs": [],
62 | "source": [
63 | "@serve.deployment\n",
64 | "def my_ray_serve_function(request):\n",
65 | " args = request.query_params[\"data\"]\n",
66 | " result = random.random() * float(args)\n",
67 | " return f\"Result: {result:.3f}\" "
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "execution_count": 4,
73 | "id": "408bc6bc-70bd-4d15-a9f9-0825253b9933",
74 | "metadata": {},
75 | "outputs": [
76 | {
77 | "name": "stderr",
78 | "output_type": "stream",
79 | "text": [
80 | "2022-04-12 18:56:09,807\tINFO api.py:618 -- Updating deployment 'my_ray_serve_function'. component=serve deployment=my_ray_serve_function\n",
81 | "\u001b[2m\u001b[36m(HTTPProxyActor pid=71609)\u001b[0m INFO: Started server process [71609]\n",
82 | "\u001b[2m\u001b[36m(ServeController pid=71592)\u001b[0m 2022-04-12 18:56:09,816\tINFO deployment_state.py:1210 -- Adding 1 replicas to deployment 'my_ray_serve_function'. component=serve deployment=my_ray_serve_function\n",
83 | "2022-04-12 18:56:11,815\tINFO api.py:633 -- Deployment 'my_ray_serve_function' is ready at `http://127.0.0.1:8000/my_ray_serve_function`. component=serve deployment=my_ray_serve_function\n"
84 | ]
85 | }
86 | ],
87 | "source": [
88 | "my_ray_serve_function.deploy()"
89 | ]
90 | },
91 | {
92 | "cell_type": "markdown",
93 | "id": "96d82a0b-0921-456a-8d1c-2a4970f08f1a",
94 | "metadata": {},
95 | "source": [
96 | "### Send Request to the function "
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": 5,
102 | "id": "5a7f4db8-5819-4a36-a39e-45b620ffb1de",
103 | "metadata": {},
104 | "outputs": [
105 | {
106 | "name": "stdout",
107 | "output_type": "stream",
108 | "text": [
109 | " 0: Result: 0.000\n",
110 | " 1: Result: 0.908\n",
111 | " 2: Result: 0.415\n",
112 | " 3: Result: 1.428\n",
113 | " 4: Result: 0.339\n"
114 | ]
115 | }
116 | ],
117 | "source": [
118 | "for i in range(5):\n",
119 | " response = requests.get(f\"http://127.0.0.1:8000/my_ray_serve_function?data={i}\").text\n",
120 | " print(f'{i:2d}: {response:}')"
121 | ]
122 | },
123 | {
124 | "cell_type": "markdown",
125 | "id": "2dde668f-0705-4c9c-88bb-bf468e7c02d1",
126 | "metadata": {},
127 | "source": [
128 | "### Create a stateful class"
129 | ]
130 | },
131 | {
132 | "cell_type": "code",
133 | "execution_count": 17,
134 | "id": "93b5247b-b7c3-4dd0-9919-f460407ce79d",
135 | "metadata": {},
136 | "outputs": [],
137 | "source": [
138 | "from random import random\n",
139 | "import starlette\n",
140 | "from starlette.requests import Request\n",
141 | "\n",
142 | "@serve.deployment\n",
143 | "class Model:\n",
144 | " \n",
145 | " def __init__(self, threshold):\n",
146 | " self.threshold = threshold\n",
147 | " \n",
148 | " def __call__(self, starlette_request):\n",
149 | " if isinstance(starlette_request, starlette.requests.Request):\n",
150 | " data = starlette_request.query_params['data']\n",
151 | " else:\n",
152 | " # Request came via a ServerHandle API method call.\n",
153 | " data = starlette_request\n",
154 | " prediction = random() + float(data) if float(data) > self.threshold else float(data)\n",
155 | " return {\"prediction\": prediction}"
156 | ]
157 | },
158 | {
159 | "cell_type": "code",
160 | "execution_count": 18,
161 | "id": "52e32071-e4d4-4d02-8421-3e542736384c",
162 | "metadata": {},
163 | "outputs": [
164 | {
165 | "name": "stderr",
166 | "output_type": "stream",
167 | "text": [
168 | "2022-04-12 19:02:07,168\tINFO api.py:618 -- Updating deployment 'Model'. component=serve deployment=Model\n",
169 | "\u001b[2m\u001b[36m(ServeController pid=71592)\u001b[0m 2022-04-12 19:02:07,272\tINFO deployment_state.py:1167 -- Stopping 1 replicas of deployment 'Model' with outdated versions. component=serve deployment=Model\n",
170 | "\u001b[2m\u001b[36m(ServeController pid=71592)\u001b[0m 2022-04-12 19:02:09,424\tINFO deployment_state.py:1210 -- Adding 1 replicas to deployment 'Model'. component=serve deployment=Model\n",
171 | "2022-04-12 19:02:11,195\tINFO api.py:633 -- Deployment 'Model' is ready at `http://127.0.0.1:8000/Model`. component=serve deployment=Model\n"
172 | ]
173 | }
174 | ],
175 | "source": [
176 | "Model.deploy(0.5)"
177 | ]
178 | },
179 | {
180 | "cell_type": "markdown",
181 | "id": "3e9c9748-eeb2-4937-89e9-5f53f123edd2",
182 | "metadata": {},
183 | "source": [
184 | "### Send requests to the model"
185 | ]
186 | },
187 | {
188 | "cell_type": "code",
189 | "execution_count": 19,
190 | "id": "f5636ab1-823b-4e12-8d6d-bae8a9c03985",
191 | "metadata": {},
192 | "outputs": [
193 | {
194 | "name": "stdout",
195 | "output_type": "stream",
196 | "text": [
197 | "prediction : {\n",
198 | " \"prediction\": 1.5609795907065314\n",
199 | "}\n",
200 | "prediction : {\n",
201 | " \"prediction\": 0.25009238923849064\n",
202 | "}\n",
203 | "prediction : {\n",
204 | " \"prediction\": 0.3763580629780887\n",
205 | "}\n",
206 | "prediction : {\n",
207 | " \"prediction\": 0.30675872742057997\n",
208 | "}\n",
209 | "prediction : {\n",
210 | " \"prediction\": 0.04218724913945959\n",
211 | "}\n"
212 | ]
213 | }
214 | ],
215 | "source": [
216 | "url = f\"http://127.0.0.1:8000/Model\"\n",
217 | "for i in range(5):\n",
218 | " print(f\"prediction : {requests.get(url, params={'data': random()}).text}\")"
219 | ]
220 | },
221 | {
222 | "cell_type": "raw",
223 | "id": "54b49569-7f61-4674-987a-19e095151a64",
224 | "metadata": {},
225 | "source": [
226 | "serve.shutdown()"
227 | ]
228 | }
229 | ],
230 | "metadata": {
231 | "kernelspec": {
232 | "display_name": "Python 3 (ipykernel)",
233 | "language": "python",
234 | "name": "python3"
235 | },
236 | "language_info": {
237 | "codemirror_mode": {
238 | "name": "ipython",
239 | "version": 3
240 | },
241 | "file_extension": ".py",
242 | "mimetype": "text/x-python",
243 | "name": "python",
244 | "nbconvert_exporter": "python",
245 | "pygments_lexer": "ipython3",
246 | "version": "3.8.12"
247 | }
248 | },
249 | "nbformat": 4,
250 | "nbformat_minor": 5
251 | }
252 |
--------------------------------------------------------------------------------
/retired/solutions/ex_10_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "51bc67b6-1425-441c-b018-ba49b6bd097b",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "sample_request_inputs = [{\n",
11 | " \"sepal length\": 6.3,\n",
12 | " \"sepal width\": 3.3,\n",
13 | " \"petal length\": 6.0,\n",
14 | " \"petal width\": 2.5\n",
15 | " },\n",
16 | " {\n",
17 | " \"sepal length\": 5.1,\n",
18 | " \"sepal width\": 3.5,\n",
19 | " \"petal length\": 1.4,\n",
20 | " \"petal width\": 0.2\n",
21 | " },\n",
22 | " {\n",
23 | " \"sepal length\": 6.4,\n",
24 | " \"sepal width\": 3.2,\n",
25 | " \"petal length\": 4.5,\n",
26 | " \"petal width\": 1.5},\n",
27 | "]"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": null,
33 | "id": "8639c07d-c973-43d9-b71a-0ab1ebe0980c",
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "for input_request in sample_request_inputs:\n",
38 | " response = requests.get(\"http://localhost:8000/regressor\",\n",
39 | " json=input_request)\n",
40 | " print(response.text)"
41 | ]
42 | }
43 | ],
44 | "metadata": {
45 | "kernelspec": {
46 | "display_name": "Python 3 (ipykernel)",
47 | "language": "python",
48 | "name": "python3"
49 | },
50 | "language_info": {
51 | "codemirror_mode": {
52 | "name": "ipython",
53 | "version": 3
54 | },
55 | "file_extension": ".py",
56 | "mimetype": "text/x-python",
57 | "name": "python",
58 | "nbconvert_exporter": "python",
59 | "pygments_lexer": "ipython3",
60 | "version": "3.8.12"
61 | }
62 | },
63 | "nbformat": 4,
64 | "nbformat_minor": 5
65 | }
66 |
--------------------------------------------------------------------------------
/retired/submit.py:
--------------------------------------------------------------------------------
1 | import ray
2 | import time
3 |
4 |
5 | @ray.remote(num_cpus=1)
6 | class Actor:
7 | def __init__(self):
8 | self.a = 1
9 |
10 | def f(self):
11 | # time.sleep(1)
12 | self.a += 1
13 | return self.a
14 |
15 |
16 | if __name__ == "__main__":
17 | # connect to the local host with RAY_ADDRESS=127.0.0.1
18 | ray.init(address="auto")
19 | actors = [Actor.remote() for _ in range(5)]
20 | refs = [a.f.remote() for a in actors]
21 | results = ray.get(refs)
22 | print(results)
23 |
24 |
25 |
--------------------------------------------------------------------------------
/slides/pydata_nyc/ray-core-tutorial-slides.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/slides/pydata_nyc/ray-core-tutorial-slides.pdf
--------------------------------------------------------------------------------
/slides/pydata_seattle/ray-core-tutorial-slides.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/slides/pydata_seattle/ray-core-tutorial-slides.pdf
--------------------------------------------------------------------------------
/slides/ucsd/ucsd_lecture.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmatrix/ray-core-tutorial/ad5f1fa700d87a9af1e21027f06f02cfdcc937f3/slides/ucsd/ucsd_lecture.pdf
--------------------------------------------------------------------------------
/solutions/ex_01_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "id": "db1a7d02-4378-4184-bd08-d29c7ae8d8ab",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "import math\n",
11 | "import numpy as np\n",
12 | "import logging\n",
13 | "from typing import List\n",
14 | "import ray"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 2,
20 | "id": "b4ef2d84-4903-429e-96c8-a24210ceec34",
21 | "metadata": {},
22 | "outputs": [],
23 | "source": [
24 | "@ray.remote\n",
25 | "def compute_intensive_func(num: int, dims=10) -> List[np.array]:\n",
26 | " dot_products = []\n",
27 | " for _ in range(num):\n",
28 | " # Create a dims x dims matrix\n",
29 | " x = np.random.rand(dims, dims)\n",
30 | " y = np.random.rand(dims, dims)\n",
31 | " \n",
32 | " # Create a dot product of itself\n",
33 | " dot_products.append(np.dot(x, y))\n",
34 | " return dot_products"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": 3,
40 | "id": "68e43170-0260-4f7b-91df-4433770145a2",
41 | "metadata": {},
42 | "outputs": [
43 | {
44 | "data": {
45 | "text/html": [
46 | "\n",
47 | "
\n",
48 | "
Ray
\n",
49 | "
\n",
70 | "
\n",
71 | " \n",
72 | " Python version: | \n",
73 | " 3.8.13 | \n",
74 | "
\n",
75 | " \n",
76 | " Ray version: | \n",
77 | " 2.3.0 | \n",
78 | "
\n",
79 | " \n",
80 | " Dashboard: | \n",
81 | " http://127.0.0.1:8265 | \n",
82 | "
\n",
83 | "\n",
84 | "
\n",
85 | "
\n",
86 | "
\n"
87 | ],
88 | "text/plain": [
89 | "RayContext(dashboard_url='127.0.0.1:8265', python_version='3.8.13', ray_version='2.3.0', ray_commit='cf7a56b4b0b648c324722df7c99c168e92ff0b45', address_info={'node_ip_address': '127.0.0.1', 'raylet_ip_address': '127.0.0.1', 'redis_address': None, 'object_store_address': '/tmp/ray/session_2023-02-26_10-33-21_402213_21042/sockets/plasma_store', 'raylet_socket_name': '/tmp/ray/session_2023-02-26_10-33-21_402213_21042/sockets/raylet', 'webui_url': '127.0.0.1:8265', 'session_dir': '/tmp/ray/session_2023-02-26_10-33-21_402213_21042', 'metrics_export_port': 61990, 'gcs_address': '127.0.0.1:55178', 'address': '127.0.0.1:55178', 'dashboard_agent_listen_port': 52365, 'node_id': 'ad21cbc2ef3080151ad0c70fe15122dfb39fdf8d0018c267ac4641bc'})"
90 | ]
91 | },
92 | "execution_count": 3,
93 | "metadata": {},
94 | "output_type": "execute_result"
95 | }
96 | ],
97 | "source": [
98 | "if ray.is_initialized:\n",
99 | " ray.shutdown()\n",
100 | "ray.init(logging_level=logging.ERROR)"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": 4,
106 | "id": "f0677e24-0b30-4831-b348-2ce8147576a8",
107 | "metadata": {},
108 | "outputs": [
109 | {
110 | "name": "stdout",
111 | "output_type": "stream",
112 | "text": [
113 | "CPU times: user 36.6 ms, sys: 11 ms, total: 47.6 ms\n",
114 | "Wall time: 58.1 ms\n"
115 | ]
116 | }
117 | ],
118 | "source": [
119 | "%%time\n",
120 | "results = [compute_intensive_func.remote(i, 5_000) for i in range(5)]"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 25,
126 | "id": "8482dfac-4043-410c-a75d-1588cfd893c7",
127 | "metadata": {},
128 | "outputs": [],
129 | "source": [
130 | "ray.shutdown()"
131 | ]
132 | }
133 | ],
134 | "metadata": {
135 | "kernelspec": {
136 | "display_name": "Python 3 (ipykernel)",
137 | "language": "python",
138 | "name": "python3"
139 | },
140 | "language_info": {
141 | "codemirror_mode": {
142 | "name": "ipython",
143 | "version": 3
144 | },
145 | "file_extension": ".py",
146 | "mimetype": "text/x-python",
147 | "name": "python",
148 | "nbconvert_exporter": "python",
149 | "pygments_lexer": "ipython3",
150 | "version": "3.8.13"
151 | }
152 | },
153 | "nbformat": 4,
154 | "nbformat_minor": 5
155 | }
156 |
--------------------------------------------------------------------------------
/solutions/ex_02_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "id": "1be69dae-83d9-43d1-81e7-41c26b683ce3",
7 | "metadata": {},
8 | "outputs": [
9 | {
10 | "name": "stdout",
11 | "output_type": "stream",
12 | "text": [
13 | "RayContext(dashboard_url='127.0.0.1:8267', python_version='3.8.12', ray_version='2.0.0.dev0', ray_commit='{{RAY_COMMIT_SHA}}', address_info={'node_ip_address': '127.0.0.1', 'raylet_ip_address': '127.0.0.1', 'redis_address': None, 'object_store_address': '/tmp/ray/session_2022-04-12_19-26-55_484801_74445/sockets/plasma_store', 'raylet_socket_name': '/tmp/ray/session_2022-04-12_19-26-55_484801_74445/sockets/raylet', 'webui_url': '127.0.0.1:8267', 'session_dir': '/tmp/ray/session_2022-04-12_19-26-55_484801_74445', 'metrics_export_port': 65382, 'gcs_address': '127.0.0.1:64612', 'address': '127.0.0.1:64612', 'node_id': '7232289a9b1cd1025eca11df0e1122621f1a665ea41c197b9d9d35c0'})\n"
14 | ]
15 | }
16 | ],
17 | "source": [
18 | "import logging\n",
19 | "from pprint import pprint\n",
20 | "import ray\n",
21 | "\n",
22 | "if ray.is_initialized:\n",
23 | " ray.shutdown()\n",
24 | "context = ray.init(logging_level=logging.ERROR)\n",
25 | "pprint(context)"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": 2,
31 | "id": "0084eab3-f381-430d-a750-74b4a8e434f8",
32 | "metadata": {},
33 | "outputs": [
34 | {
35 | "name": "stdout",
36 | "output_type": "stream",
37 | "text": [
38 | "Dashboard url: http://127.0.0.1:8267\n"
39 | ]
40 | }
41 | ],
42 | "source": [
43 | "print(f\"Dashboard url: http://{context.address_info['webui_url']}\")"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": 6,
49 | "id": "8110da95-01b2-4b73-ba13-f7cfea166329",
50 | "metadata": {},
51 | "outputs": [],
52 | "source": [
53 | "@ray.remote\n",
54 | "def my_function (num_list):\n",
55 | " return sum(num_list)"
56 | ]
57 | },
58 | {
59 | "cell_type": "markdown",
60 | "id": "7bf709bd-217c-4553-80c1-042c7dddb34f",
61 | "metadata": {},
62 | "source": [
63 | "### Method 1\n",
64 | "\n",
65 | "Without comprehension"
66 | ]
67 | },
68 | {
69 | "cell_type": "code",
70 | "execution_count": 11,
71 | "id": "7618f6df-f2b6-4286-9dae-fe24497caae0",
72 | "metadata": {},
73 | "outputs": [
74 | {
75 | "data": {
76 | "text/plain": [
77 | "[ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000015000000),\n",
78 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000016000000),\n",
79 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000017000000),\n",
80 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000018000000),\n",
81 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000019000000),\n",
82 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001a000000),\n",
83 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001b000000),\n",
84 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001c000000),\n",
85 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001d000000),\n",
86 | " ObjectRef(00ffffffffffffffffffffffffffffffffffffff010000001e000000)]"
87 | ]
88 | },
89 | "execution_count": 11,
90 | "metadata": {},
91 | "output_type": "execute_result"
92 | }
93 | ],
94 | "source": [
95 | "obj_refs = [ray.put(i) for i in range(10)]\n",
96 | "obj_refs"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": 13,
102 | "id": "6835d594-e51d-4da8-a53c-01d7d6c39e44",
103 | "metadata": {},
104 | "outputs": [
105 | {
106 | "data": {
107 | "text/plain": [
108 | "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
109 | ]
110 | },
111 | "execution_count": 13,
112 | "metadata": {},
113 | "output_type": "execute_result"
114 | }
115 | ],
116 | "source": [
117 | "values = ray.get(obj_refs)\n",
118 | "values"
119 | ]
120 | },
121 | {
122 | "cell_type": "code",
123 | "execution_count": 14,
124 | "id": "4a48c181-a6c8-41fe-bf71-78ceaaff2fef",
125 | "metadata": {},
126 | "outputs": [],
127 | "source": [
128 | "sum_obj_ref = my_function.remote(values)"
129 | ]
130 | },
131 | {
132 | "cell_type": "code",
133 | "execution_count": 15,
134 | "id": "3ec83055-db03-4651-959b-26d116905ea5",
135 | "metadata": {},
136 | "outputs": [
137 | {
138 | "data": {
139 | "text/plain": [
140 | "45"
141 | ]
142 | },
143 | "execution_count": 15,
144 | "metadata": {},
145 | "output_type": "execute_result"
146 | }
147 | ],
148 | "source": [
149 | "ray.get(sum_obj_ref)"
150 | ]
151 | },
152 | {
153 | "cell_type": "markdown",
154 | "id": "85096fa6-8cea-4b50-aff7-3b4857df64ec",
155 | "metadata": {},
156 | "source": [
157 | "### Method 2\n",
158 | "Using comprehension"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 16,
164 | "id": "33f2a5d0-ea98-4997-9cde-c3cf7d801f85",
165 | "metadata": {},
166 | "outputs": [
167 | {
168 | "data": {
169 | "text/plain": [
170 | "45"
171 | ]
172 | },
173 | "execution_count": 16,
174 | "metadata": {},
175 | "output_type": "execute_result"
176 | }
177 | ],
178 | "source": [
179 | "ray.get(my_function.remote(ray.get([ray.put(i) for i in range(10)])))"
180 | ]
181 | }
182 | ],
183 | "metadata": {
184 | "kernelspec": {
185 | "display_name": "Python 3 (ipykernel)",
186 | "language": "python",
187 | "name": "python3"
188 | },
189 | "language_info": {
190 | "codemirror_mode": {
191 | "name": "ipython",
192 | "version": 3
193 | },
194 | "file_extension": ".py",
195 | "mimetype": "text/x-python",
196 | "name": "python",
197 | "nbconvert_exporter": "python",
198 | "pygments_lexer": "ipython3",
199 | "version": "3.8.13"
200 | }
201 | },
202 | "nbformat": 4,
203 | "nbformat_minor": 5
204 | }
205 |
--------------------------------------------------------------------------------
/solutions/ex_03_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 6,
6 | "id": "b456a148-3f34-468f-a889-3f319489444b",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "import logging\n",
11 | "import time\n",
12 | "import os\n",
13 | "import math\n",
14 | "import ray\n",
15 | "import random\n",
16 | "import tqdm\n",
17 | "from typing import Dict, Tuple, List\n",
18 | "from random import randint\n",
19 | "import numpy as np"
20 | ]
21 | },
22 | {
23 | "cell_type": "code",
24 | "execution_count": 7,
25 | "id": "834f3f49-5ce3-4942-a8d2-7aa490fdb73b",
26 | "metadata": {},
27 | "outputs": [
28 | {
29 | "data": {
30 | "text/html": [
31 | "\n",
32 | "
\n",
33 | "
Ray
\n",
34 | "
\n",
55 | "
\n",
56 | " \n",
57 | " Python version: | \n",
58 | " 3.8.13 | \n",
59 | "
\n",
60 | " \n",
61 | " Ray version: | \n",
62 | " 2.3.0 | \n",
63 | "
\n",
64 | " \n",
65 | " Dashboard: | \n",
66 | " http://127.0.0.1:8267 | \n",
67 | "
\n",
68 | "\n",
69 | "
\n",
70 | "
\n",
71 | "
\n"
72 | ],
73 | "text/plain": [
74 | "RayContext(dashboard_url='127.0.0.1:8267', python_version='3.8.13', ray_version='2.3.0', ray_commit='cf7a56b4b0b648c324722df7c99c168e92ff0b45', address_info={'node_ip_address': '127.0.0.1', 'raylet_ip_address': '127.0.0.1', 'redis_address': None, 'object_store_address': '/tmp/ray/session_2023-02-26_14-26-54_960980_73058/sockets/plasma_store', 'raylet_socket_name': '/tmp/ray/session_2023-02-26_14-26-54_960980_73058/sockets/raylet', 'webui_url': '127.0.0.1:8267', 'session_dir': '/tmp/ray/session_2023-02-26_14-26-54_960980_73058', 'metrics_export_port': 59961, 'gcs_address': '127.0.0.1:57533', 'address': '127.0.0.1:57533', 'dashboard_agent_listen_port': 52365, 'node_id': 'c707f34390057228d0d268e603e8536ce4d45fa04b7cc2a6f45e9548'})"
75 | ]
76 | },
77 | "execution_count": 7,
78 | "metadata": {},
79 | "output_type": "execute_result"
80 | }
81 | ],
82 | "source": [
83 | "if ray.is_initialized:\n",
84 | " ray.shutdown()\n",
85 | "ray.init(logging_level=logging.ERROR)"
86 | ]
87 | },
88 | {
89 | "cell_type": "code",
90 | "execution_count": 8,
91 | "id": "1098ee33-9bec-4345-ba87-4a1ed9b87437",
92 | "metadata": {},
93 | "outputs": [],
94 | "source": [
95 | "class ActorCls:\n",
96 | " def __init__(self, name: str):\n",
97 | " self.name = name\n",
98 | " self.method_calls = {\"method\": 0}\n",
99 | "\n",
100 | " def method(self, **args) -> None:\n",
101 | " # Overwrite this method in the subclass\n",
102 | " pass\n",
103 | "\n",
104 | " def get_all_method_calls(self) -> Tuple[str, Dict[str, int]]:\n",
105 | " return self.get_name(), self.method_calls\n",
106 | " \n",
107 | " def get_name(self) -> str:\n",
108 | " return self.name"
109 | ]
110 | },
111 | {
112 | "cell_type": "code",
113 | "execution_count": 9,
114 | "id": "5ce35e3d-566e-493a-99c1-560eb1ca0788",
115 | "metadata": {},
116 | "outputs": [],
117 | "source": [
118 | "@ray.remote\n",
119 | "class ActorClsOne(ActorCls):\n",
120 | " \n",
121 | " def __init__(self, name: str):\n",
122 | " super().__init__(name)\n",
123 | " \n",
124 | " def method(self, **args) -> None:\n",
125 | " # do something with kwargs here\n",
126 | " time.sleep(args[\"timeout\"])\n",
127 | " \n",
128 | " # update the respective counter\n",
129 | " self.method_calls[\"method\"] += 1"
130 | ]
131 | },
132 | {
133 | "cell_type": "code",
134 | "execution_count": 10,
135 | "id": "93940068-fde2-48da-9621-c7bb769cf300",
136 | "metadata": {},
137 | "outputs": [],
138 | "source": [
139 | "@ray.remote\n",
140 | "class ActorClsTwo(ActorCls):\n",
141 | " \n",
142 | " def __init__(self, name: str):\n",
143 | " super().__init__(name)\n",
144 | " \n",
145 | " def method(self, **args) -> None:\n",
146 | " # do something with kwargs here\n",
147 | " time.sleep(args[\"timeout\"])\n",
148 | " \n",
149 | " # update the respective counter\n",
150 | " self.method_calls[\"method\"] += 1"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "execution_count": 11,
156 | "id": "42b7346a-e3e0-4074-a426-8753b1df687e",
157 | "metadata": {},
158 | "outputs": [],
159 | "source": [
160 | "@ray.remote\n",
161 | "class ActorClsThree(ActorCls):\n",
162 | " \n",
163 | " def __init__(self, name: str):\n",
164 | " super().__init__(name)\n",
165 | " \n",
166 | " def method(self, **args) -> None:\n",
167 | " # do something with kwargs here\n",
168 | " time.sleep(args[\"timeout\"])\n",
169 | " \n",
170 | " # update the respective counter\n",
171 | " self.method_calls[\"method\"] += 1"
172 | ]
173 | },
174 | {
175 | "cell_type": "code",
176 | "execution_count": 12,
177 | "id": "8aa5fc45-b15b-4c2d-aec1-9c051d37c423",
178 | "metadata": {},
179 | "outputs": [],
180 | "source": [
181 | "actor_one = ActorClsOne.remote(\"ActorClsOne\")\n",
182 | "actor_two = ActorClsTwo.remote(\"ActorClsTwo\")\n",
183 | "actor_three = ActorClsTwo.remote(\"ActorClsThree\")"
184 | ]
185 | },
186 | {
187 | "cell_type": "code",
188 | "execution_count": 14,
189 | "id": "c30cb397-2f64-491c-9a34-60f3687e9b5d",
190 | "metadata": {},
191 | "outputs": [],
192 | "source": [
193 | "# A list of Actor classes\n",
194 | "CALLERS_NAMES = [\"ActorClsOne\", \"ActorClsTwo\", \"ActorClsThree\"]\n",
195 | "\n",
196 | "# A dictionary of Actor instances\n",
197 | "CALLERS_CLS_DICT = {\"ActorClsOne\": actor_one, \n",
198 | " \"ActorClsTwo\": actor_two,\n",
199 | " \"ActorClsThree\": actor_three}"
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": 15,
205 | "id": "22a4f44a-77b2-4459-a863-84b986eb5a1b",
206 | "metadata": {},
207 | "outputs": [
208 | {
209 | "name": "stdout",
210 | "output_type": "stream",
211 | "text": [
212 | "State of counts in this execution: {'ActorClsOne': 3, 'ActorClsTwo': 8, 'ActorClsThree': 4}\n",
213 | "State of counts in this execution: {'ActorClsOne': 6, 'ActorClsTwo': 14, 'ActorClsThree': 10}\n",
214 | "State of counts in this execution: {'ActorClsOne': 10, 'ActorClsTwo': 17, 'ActorClsThree': 18}\n"
215 | ]
216 | }
217 | ],
218 | "source": [
219 | "count_dict = {\"ActorClsOne\": 0, \"ActorClsTwo\": 0, \"ActorClsThree\": 0}\n",
220 | "for _ in range(len(CALLERS_NAMES)): \n",
221 | " for _ in range(15):\n",
222 | " name = random.choice(CALLERS_NAMES)\n",
223 | " count_dict[name] += 1 \n",
224 | " CALLERS_CLS_DICT[name].method.remote(timeout=1, store=\"mongo_db\") if name == \"ActorClsOne\" else CALLERS_CLS_DICT[name].method.remote(timeout=1.5, store=\"delta\")\n",
225 | " \n",
226 | " print(f\"State of counts in this execution: {count_dict}\")\n",
227 | " time.sleep(0.5)"
228 | ]
229 | },
230 | {
231 | "cell_type": "code",
232 | "execution_count": 16,
233 | "id": "a2897704-2400-4731-b6e9-44164aa46db8",
234 | "metadata": {},
235 | "outputs": [
236 | {
237 | "name": "stdout",
238 | "output_type": "stream",
239 | "text": [
240 | "[('ActorClsOne', {'method': 10}), ('ActorClsTwo', {'method': 17}), ('ActorClsThree', {'method': 18})]\n"
241 | ]
242 | }
243 | ],
244 | "source": [
245 | "print(ray.get([CALLERS_CLS_DICT[name].get_all_method_calls.remote() for name in CALLERS_NAMES]))"
246 | ]
247 | },
248 | {
249 | "cell_type": "code",
250 | "execution_count": 17,
251 | "id": "8a2d525b-da65-41b2-bf32-f950926bbd31",
252 | "metadata": {},
253 | "outputs": [],
254 | "source": [
255 | "ray.shutdown()"
256 | ]
257 | }
258 | ],
259 | "metadata": {
260 | "kernelspec": {
261 | "display_name": "Python 3 (ipykernel)",
262 | "language": "python",
263 | "name": "python3"
264 | },
265 | "language_info": {
266 | "codemirror_mode": {
267 | "name": "ipython",
268 | "version": 3
269 | },
270 | "file_extension": ".py",
271 | "mimetype": "text/x-python",
272 | "name": "python",
273 | "nbconvert_exporter": "python",
274 | "pygments_lexer": "ipython3",
275 | "version": "3.8.13"
276 | }
277 | },
278 | "nbformat": 4,
279 | "nbformat_minor": 5
280 | }
281 |
--------------------------------------------------------------------------------
/solutions/ex_04_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "id": "e425ccaf-273b-4126-8b2b-147dbbd8aa8a",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "import logging\n",
11 | "import time\n",
12 | "import ray\n",
13 | "import random\n",
14 | "from random import randint\n",
15 | "import numpy as np"
16 | ]
17 | },
18 | {
19 | "cell_type": "code",
20 | "execution_count": 2,
21 | "id": "2f61c376-5c2f-4f26-bd57-1b50624dadbd",
22 | "metadata": {},
23 | "outputs": [],
24 | "source": [
25 | "from collections import defaultdict\n",
26 | "@ray.remote\n",
27 | "class LoggingActor(object):\n",
28 | " def __init__(self):\n",
29 | " # create a container of dictionaries.\n",
30 | " self.logs = defaultdict(list)\n",
31 | " \n",
32 | " # log the message for a particular experiment in its \n",
33 | " # respective dictionary\n",
34 | " def log(self, index, message):\n",
35 | " self.logs[index].append(message)\n",
36 | " \n",
37 | " # fetch all logs as collection\n",
38 | " def get_logs(self):\n",
39 | " return dict(self.logs)\n",
40 | " \n",
41 | "@ray.remote\n",
42 | "def run_experiment(experiment_index, logging_actor):\n",
43 | " for i in range(9):\n",
44 | " # pretend this is an experiment that produces a nine results for \n",
45 | " # experiment result; in our case it's just a simple message \n",
46 | " # Push a logging message to the actor.\n",
47 | " exp_key = f\"experiment-{experiment_index}\"\n",
48 | " logging_actor.log.remote(exp_key, 'On iteration {}'.format(i)) "
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": 3,
54 | "id": "566abe08-0af6-42e7-ba57-532166f4d0ce",
55 | "metadata": {},
56 | "outputs": [
57 | {
58 | "data": {
59 | "text/html": [
60 | "\n",
61 | "
\n",
62 | "
Ray
\n",
63 | "
\n",
84 | "
\n",
85 | " \n",
86 | " Python version: | \n",
87 | " 3.8.13 | \n",
88 | "
\n",
89 | " \n",
90 | " Ray version: | \n",
91 | " 2.0.1 | \n",
92 | "
\n",
93 | " \n",
94 | " Dashboard: | \n",
95 | " http://127.0.0.1:8265 | \n",
96 | "
\n",
97 | "\n",
98 | "
\n",
99 | "
\n",
100 | "
\n"
101 | ],
102 | "text/plain": [
103 | "RayContext(dashboard_url='127.0.0.1:8265', python_version='3.8.13', ray_version='2.0.1', ray_commit='03b6bc7b5a305877501110ec04710a9c57011479', address_info={'node_ip_address': '127.0.0.1', 'raylet_ip_address': '127.0.0.1', 'redis_address': None, 'object_store_address': '/tmp/ray/session_2022-11-10_04-04-44_290983_62756/sockets/plasma_store', 'raylet_socket_name': '/tmp/ray/session_2022-11-10_04-04-44_290983_62756/sockets/raylet', 'webui_url': '127.0.0.1:8265', 'session_dir': '/tmp/ray/session_2022-11-10_04-04-44_290983_62756', 'metrics_export_port': 55660, 'gcs_address': '127.0.0.1:52014', 'address': '127.0.0.1:52014', 'dashboard_agent_listen_port': 52365, 'node_id': '155073a0c7205bde87bbee5cc38570f21f97730a7032ebdac36ba251'})"
104 | ]
105 | },
106 | "execution_count": 3,
107 | "metadata": {},
108 | "output_type": "execute_result"
109 | }
110 | ],
111 | "source": [
112 | "if ray.is_initialized:\n",
113 | " ray.shutdown()\n",
114 | "ray.init(logging_level=logging.ERROR)"
115 | ]
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "id": "272895a1-4fb1-4235-9ddd-65e76930554e",
120 | "metadata": {},
121 | "source": [
122 | "Run three experiments."
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "execution_count": 4,
128 | "id": "cd2a3f51-92a1-4ff9-8d22-56b47ebf69da",
129 | "metadata": {},
130 | "outputs": [],
131 | "source": [
132 | "logging_actor = LoggingActor.remote()\n",
133 | "experiment_ids = []\n",
134 | "# Run three different experiments\n",
135 | "for i in range(3):\n",
136 | " experiment_ids.append(run_experiment.remote(i, logging_actor))"
137 | ]
138 | },
139 | {
140 | "cell_type": "markdown",
141 | "id": "50212dd0-bd49-48f0-b5b2-27cb0baa3d52",
142 | "metadata": {},
143 | "source": [
144 | "### Fetch the results \n",
145 | "\n",
146 | "For each experement, we will have 9 iteration results"
147 | ]
148 | },
149 | {
150 | "cell_type": "code",
151 | "execution_count": 5,
152 | "id": "3ed4fc03-339f-4866-a3ef-dfd12051d078",
153 | "metadata": {},
154 | "outputs": [
155 | {
156 | "name": "stdout",
157 | "output_type": "stream",
158 | "text": [
159 | "{'experiment-0': ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8'], 'experiment-1': ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8'], 'experiment-2': ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8']}\n",
160 | "{'experiment-0': ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8'], 'experiment-1': ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8'], 'experiment-2': ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8']}\n",
161 | "{'experiment-0': ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8'], 'experiment-1': ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8'], 'experiment-2': ['On iteration 0', 'On iteration 1', 'On iteration 2', 'On iteration 3', 'On iteration 4', 'On iteration 5', 'On iteration 6', 'On iteration 7', 'On iteration 8']}\n"
162 | ]
163 | }
164 | ],
165 | "source": [
166 | "for i in range(3):\n",
167 | " time.sleep(1)\n",
168 | " logs = logging_actor.get_logs.remote()\n",
169 | " print(ray.get(logs))"
170 | ]
171 | },
172 | {
173 | "cell_type": "code",
174 | "execution_count": 6,
175 | "id": "13c39791-63e1-4563-9d7c-e9aab7700d34",
176 | "metadata": {},
177 | "outputs": [],
178 | "source": [
179 | "ray.shutdown()"
180 | ]
181 | }
182 | ],
183 | "metadata": {
184 | "kernelspec": {
185 | "display_name": "Python 3 (ipykernel)",
186 | "language": "python",
187 | "name": "python3"
188 | },
189 | "language_info": {
190 | "codemirror_mode": {
191 | "name": "ipython",
192 | "version": 3
193 | },
194 | "file_extension": ".py",
195 | "mimetype": "text/x-python",
196 | "name": "python",
197 | "nbconvert_exporter": "python",
198 | "pygments_lexer": "ipython3",
199 | "version": "3.8.13"
200 | }
201 | },
202 | "nbformat": 4,
203 | "nbformat_minor": 5
204 | }
205 |
--------------------------------------------------------------------------------
/solutions/ex_05_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "id": "de7fdaf6-ab3a-4bb1-9c86-880e7b70ca01",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "def task(n):\n",
11 | " # Simulate a long intensive task\n",
12 | " time.sleep(0.5 * n)\n",
13 | " \n",
14 | " # do some matrix computation and return results\n",
15 | " array_1 = np.random.randint(n*50, size=n) * 0.05\n",
16 | " array_2 = np.random.randint(n * 50, size=n) * 0.03\n",
17 | " \n",
18 | " return np.sum(array_1) + np.sum(array_2)"
19 | ]
20 | }
21 | ],
22 | "metadata": {
23 | "kernelspec": {
24 | "display_name": "Python 3 (ipykernel)",
25 | "language": "python",
26 | "name": "python3"
27 | },
28 | "language_info": {
29 | "codemirror_mode": {
30 | "name": "ipython",
31 | "version": 3
32 | },
33 | "file_extension": ".py",
34 | "mimetype": "text/x-python",
35 | "name": "python",
36 | "nbconvert_exporter": "python",
37 | "pygments_lexer": "ipython3",
38 | "version": "3.8.13"
39 | }
40 | },
41 | "nbformat": 4,
42 | "nbformat_minor": 5
43 | }
44 |
--------------------------------------------------------------------------------
/solutions/ex_07_solutions.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "86278823-aee6-4cab-b9bd-ccde1a926182",
6 | "metadata": {},
7 | "source": [
8 | "### Adding a new column"
9 | ]
10 | },
11 | {
12 | "cell_type": "code",
13 | "execution_count": null,
14 | "id": "8ae90694-0926-44a8-8b70-2d4b8e986aa2",
15 | "metadata": {},
16 | "outputs": [],
17 | "source": [
18 | "new_ds = arrow_ds.add_colum(\"age\", lambda df: random.randint(21,65))\n",
19 | "new_ds.schema()"
20 | ]
21 | },
22 | {
23 | "cell_type": "code",
24 | "execution_count": null,
25 | "id": "44a8009f-f6b7-47c8-be47-1036cc086215",
26 | "metadata": {},
27 | "outputs": [],
28 | "source": [
29 | "new_ds.take(1)"
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "id": "5f5e9b47-77f2-4518-a741-9cf344cd557b",
35 | "metadata": {},
36 | "source": [
37 | "### Filter by gender (U)"
38 | ]
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": null,
43 | "id": "a35fd359-480d-4695-9807-45087dd96803",
44 | "metadata": {},
45 | "outputs": [],
46 | "source": [
47 | "arrow_ds.map_batches(lambda df: df[df[\"gender\"] == \"U\"]).take(3)"
48 | ]
49 | },
50 | {
51 | "cell_type": "markdown",
52 | "id": "72e8ca22-348b-4bbf-8971-819d7e3fcd55",
53 | "metadata": {},
54 | "source": [
55 | "### Groupby property"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "id": "fab8ff59-7560-4751-9ebe-4bff3ee4cf3e",
62 | "metadata": {},
63 | "outputs": [],
64 | "source": [
65 | "results = arrow_ds.groupby(\"property\").count()\n",
66 | "results.show()"
67 | ]
68 | },
69 | {
70 | "cell_type": "markdown",
71 | "id": "13851d83-bfec-4b01-8da6-2450229e78de",
72 | "metadata": {},
73 | "source": [
74 | "### Modify pipeline function"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": null,
80 | "id": "1cfcff5f-ddb5-493c-bf25-bf478f167bd5",
81 | "metadata": {},
82 | "outputs": [],
83 | "source": [
84 | "def count_tx(row: ray.data.impl.arrow_block.ArrowRow) -> int:\n",
85 | " return 1 if row['state'] == \"TX\" and row[\"defaulted\"] and row['marital_status' == 'married'] and else 0"
86 | ]
87 | }
88 | ],
89 | "metadata": {
90 | "kernelspec": {
91 | "display_name": "Python 3 (ipykernel)",
92 | "language": "python",
93 | "name": "python3"
94 | },
95 | "language_info": {
96 | "codemirror_mode": {
97 | "name": "ipython",
98 | "version": 3
99 | },
100 | "file_extension": ".py",
101 | "mimetype": "text/x-python",
102 | "name": "python",
103 | "nbconvert_exporter": "python",
104 | "pygments_lexer": "ipython3",
105 | "version": "3.8.13"
106 | }
107 | },
108 | "nbformat": 4,
109 | "nbformat_minor": 5
110 | }
111 |
--------------------------------------------------------------------------------
/tasks_helper_utils.py:
--------------------------------------------------------------------------------
1 | import os
2 | import requests
3 | import random
4 | import time
5 | import tqdm
6 | from pathlib import Path
7 | from PIL import Image, ImageFilter
8 | from typing import List, Tuple
9 | import torch
10 | import numpy as np
11 | import pandas as pd
12 | import matplotlib.pyplot as plt
13 | from torchvision import transforms as T
14 | import ray
15 |
16 |
17 | #
18 | # borrowed URLs ideas and heavily modified from https://analyticsindiamag.com/how-to-run-python-code-concurrently-using-multithreading/
19 | #
20 |
21 | URLS = [
22 | 'https://images.pexels.com/photos/305821/pexels-photo-305821.jpeg',
23 | 'https://images.pexels.com/photos/509922/pexels-photo-509922.jpeg',
24 | 'https://images.pexels.com/photos/325812/pexels-photo-325812.jpeg',
25 | 'https://images.pexels.com/photos/1252814/pexels-photo-1252814.jpeg',
26 | 'https://images.pexels.com/photos/1420709/pexels-photo-1420709.jpeg',
27 | 'https://images.pexels.com/photos/963486/pexels-photo-963486.jpeg',
28 | 'https://images.pexels.com/photos/1557183/pexels-photo-1557183.jpeg',
29 | 'https://images.pexels.com/photos/3023211/pexels-photo-3023211.jpeg',
30 | 'https://images.pexels.com/photos/1031641/pexels-photo-1031641.jpeg',
31 | 'https://images.pexels.com/photos/439227/pexels-photo-439227.jpeg',
32 | 'https://images.pexels.com/photos/696644/pexels-photo-696644.jpeg',
33 | 'https://images.pexels.com/photos/911254/pexels-photo-911254.jpeg',
34 | 'https://images.pexels.com/photos/1001990/pexels-photo-1001990.jpeg',
35 | 'https://images.pexels.com/photos/3518623/pexels-photo-3518623.jpeg',
36 | 'https://images.pexels.com/photos/916044/pexels-photo-916044.jpeg',
37 | 'https://images.pexels.com/photos/2253879/pexels-photo-2253879.jpeg',
38 | 'https://images.pexels.com/photos/3316918/pexels-photo-3316918.jpeg',
39 | 'https://images.pexels.com/photos/942317/pexels-photo-942317.jpeg',
40 | 'https://images.pexels.com/photos/1090638/pexels-photo-1090638.jpeg',
41 | 'https://images.pexels.com/photos/1279813/pexels-photo-1279813.jpeg',
42 | 'https://images.pexels.com/photos/434645/pexels-photo-434645.jpeg',
43 | 'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg',
44 | 'https://images.pexels.com/photos/1080696/pexels-photo-1080696.jpeg',
45 | 'https://images.pexels.com/photos/271816/pexels-photo-271816.jpeg',
46 | 'https://images.pexels.com/photos/421927/pexels-photo-421927.jpeg',
47 | 'https://images.pexels.com/photos/302428/pexels-photo-302428.jpeg',
48 | 'https://images.pexels.com/photos/443383/pexels-photo-443383.jpeg',
49 | 'https://images.pexels.com/photos/3685175/pexels-photo-3685175.jpeg',
50 | 'https://images.pexels.com/photos/2885578/pexels-photo-2885578.jpeg',
51 | 'https://images.pexels.com/photos/3530116/pexels-photo-3530116.jpeg',
52 | 'https://images.pexels.com/photos/9668911/pexels-photo-9668911.jpeg',
53 | 'https://images.pexels.com/photos/14704971/pexels-photo-14704971.jpeg',
54 | 'https://images.pexels.com/photos/13865510/pexels-photo-13865510.jpeg',
55 | 'https://images.pexels.com/photos/6607387/pexels-photo-6607387.jpeg',
56 | 'https://images.pexels.com/photos/13716813/pexels-photo-13716813.jpeg',
57 | 'https://images.pexels.com/photos/14690500/pexels-photo-14690500.jpeg',
58 | 'https://images.pexels.com/photos/14690501/pexels-photo-14690501.jpeg',
59 | 'https://images.pexels.com/photos/14615366/pexels-photo-14615366.jpeg',
60 | 'https://images.pexels.com/photos/14344696/pexels-photo-14344696.jpeg',
61 | 'https://images.pexels.com/photos/14661919/pexels-photo-14661919.jpeg',
62 | 'https://images.pexels.com/photos/5977791/pexels-photo-5977791.jpeg',
63 | 'https://images.pexels.com/photos/5211747/pexels-photo-5211747.jpeg',
64 | 'https://images.pexels.com/photos/5995657/pexels-photo-5995657.jpeg',
65 | 'https://images.pexels.com/photos/8574183/pexels-photo-8574183.jpeg',
66 | 'https://images.pexels.com/photos/14690503/pexels-photo-14690503.jpeg',
67 | 'https://images.pexels.com/photos/2100941/pexels-photo-2100941.jpeg',
68 | 'https://images.pexels.com/photos/210019/pexels-photo-210019.jpeg',
69 | 'https://images.pexels.com/photos/112460/pexels-photo-112460.jpeg',
70 | 'https://images.pexels.com/photos/116675/pexels-photo-116675.jpeg',
71 | 'https://images.pexels.com/photos/3586966/pexels-photo-3586966.jpeg',
72 | 'https://images.pexels.com/photos/313782/pexels-photo-313782.jpeg',
73 | 'https://www.nasa.gov/centers/stennis/images/content/702979main_SSC-2012-01487.jpg',
74 | 'https://live.staticflickr.com/2443/3984080835_71b0426844_b.jpg',
75 | 'https://www.aero.jaxa.jp/eng/facilities/aeroengine/images/th_aeroengine05.jpg',
76 | 'https://images.pexels.com/photos/370717/pexels-photo-370717.jpeg',
77 | 'https://images.pexels.com/photos/1323550/pexels-photo-1323550.jpeg',
78 | 'https://images.pexels.com/photos/11374974/pexels-photo-11374974.jpeg',
79 | 'https://images.pexels.com/photos/408951/pexels-photo-408951.jpeg',
80 | 'https://images.pexels.com/photos/3889870/pexels-photo-3889870.jpeg',
81 | 'https://images.pexels.com/photos/1774389/pexels-photo-1774389.jpeg',
82 | 'https://images.pexels.com/photos/3889854/pexels-photo-3889854.jpeg',
83 | 'https://images.pexels.com/photos/2196578/pexels-photo-2196578.jpeg',
84 | 'https://images.pexels.com/photos/2885320/pexels-photo-2885320.jpeg',
85 | 'https://images.pexels.com/photos/7189303/pexels-photo-7189303.jpeg',
86 | 'https://images.pexels.com/photos/9697598/pexels-photo-9697598.jpeg',
87 | 'https://images.pexels.com/photos/6431298/pexels-photo-6431298.jpeg',
88 | 'https://images.pexels.com/photos/7131157/pexels-photo-7131157.jpeg',
89 | 'https://images.pexels.com/photos/4840134/pexels-photo-4840134.jpeg',
90 | 'https://images.pexels.com/photos/5359974/pexels-photo-5359974.jpeg',
91 | 'https://images.pexels.com/photos/3889854/pexels-photo-3889854.jpeg',
92 | 'https://images.pexels.com/photos/1753272/pexels-photo-1753272.jpeg',
93 | 'https://images.pexels.com/photos/2328863/pexels-photo-2328863.jpeg',
94 | 'https://images.pexels.com/photos/6102161/pexels-photo-6102161.jpeg',
95 | 'https://images.pexels.com/photos/6101986/pexels-photo-6101986.jpeg',
96 | 'https://images.pexels.com/photos/3334492/pexels-photo-3334492.jpeg',
97 | 'https://images.pexels.com/photos/5708915/pexels-photo-5708915.jpeg',
98 | 'https://images.pexels.com/photos/5708913/pexels-photo-5708913.jpeg',
99 | 'https://images.pexels.com/photos/6102436/pexels-photo-6102436.jpeg',
100 | 'https://images.pexels.com/photos/6102144/pexels-photo-6102144.jpeg',
101 | 'https://images.pexels.com/photos/6102003/pexels-photo-6102003.jpeg',
102 | 'https://images.pexels.com/photos/6194087/pexels-photo-6194087.jpeg',
103 | 'https://images.pexels.com/photos/5847900/pexels-photo-5847900.jpeg',
104 | 'https://images.pexels.com/photos/1671479/pexels-photo-1671479.jpeg',
105 | 'https://images.pexels.com/photos/3335507/pexels-photo-3335507.jpeg',
106 | 'https://images.pexels.com/photos/6102522/pexels-photo-6102522.jpeg',
107 | 'https://images.pexels.com/photos/6211095/pexels-photo-6211095.jpeg',
108 | 'https://images.pexels.com/photos/720347/pexels-photo-720347.jpeg',
109 | 'https://images.pexels.com/photos/3516015/pexels-photo-3516015.jpeg',
110 | 'https://images.pexels.com/photos/3325717/pexels-photo-3325717.jpeg',
111 | 'https://images.pexels.com/photos/849835/pexels-photo-849835.jpeg',
112 | 'https://images.pexels.com/photos/302743/pexels-photo-302743.jpeg',
113 | 'https://images.pexels.com/photos/167699/pexels-photo-167699.jpeg',
114 | 'https://images.pexels.com/photos/259620/pexels-photo-259620.jpeg',
115 | 'https://images.pexels.com/photos/300857/pexels-photo-300857.jpeg',
116 | 'https://images.pexels.com/photos/789380/pexels-photo-789380.jpeg',
117 | 'https://images.pexels.com/photos/735987/pexels-photo-735987.jpeg',
118 | 'https://images.pexels.com/photos/572897/pexels-photo-572897.jpeg',
119 | 'https://images.pexels.com/photos/300857/pexels-photo-300857.jpeg',
120 | 'https://images.pexels.com/photos/760971/pexels-photo-760971.jpeg',
121 | 'https://images.pexels.com/photos/789382/pexels-photo-789382.jpeg',
122 | 'https://images.pexels.com/photos/33041/antelope-canyon-lower-canyon-arizona.jpg',
123 | 'https://images.pexels.com/photos/1004665/pexels-photo-1004665.jpeg'
124 | ]
125 | THUMB_SIZE = (64, 64)
126 |
127 | def extract_times(lst: Tuple[int, float]) -> List[float]:
128 | """
129 | Given a list of Tuples[batch_size, execution_time] extract the latter
130 | """
131 | times = [t[1] for t in lst]
132 | return times
133 |
134 | def plot_times(batches: List[int], s_lst: List[float], d_lst: List[float]) -> None:
135 | """
136 | Plot the execution times for serail vs distributed for each respective batch size of images
137 | """
138 | s_times = extract_times(s_lst)
139 | d_times = extract_times(d_lst)
140 | data = {'batches': batches,
141 | 'serial' : s_times,
142 | 'distributed': d_times}
143 |
144 | df = pd.DataFrame(data)
145 | df.plot(x="batches", y=["serial", "distributed"], kind="bar")
146 | plt.ylabel('Times in sec', fontsize=12)
147 | plt.xlabel('Number of Batches of Images', fontsize=12)
148 | plt.grid(False)
149 | plt.show()
150 |
151 | def display_random_images(image_list: List[str], n: int=3) -> None:
152 | """
153 | Display a grid of images, default 3 of images we want to process
154 | """
155 | random_samples_idx = random.sample(range(len(image_list)), k=n)
156 | plt.figure(figsize=(16, 8))
157 | for i, targ_sample in enumerate(random_samples_idx):
158 | plt.subplot(1, n, i+1)
159 | img = Image.open(image_list[targ_sample])
160 | img_as_array = np.asarray(img)
161 | plt.imshow(img_as_array)
162 | title = f"\nshape: {img.size}"
163 | plt.axis("off")
164 | plt.title(title)
165 | plt.show()
166 |
167 | def download_images(url: str, data_dir: str) -> None:
168 | """
169 | Given a URL and the image data directory, fetch the URL and save it in the data directory
170 | """
171 | img_data = requests.get(url).content
172 | img_name = url.split("/")[4]
173 | img_name = f"{data_dir}/{img_name}.jpg"
174 | with open(img_name, 'wb+') as f:
175 | f.write(img_data)
176 |
177 | def insert_into_object_store(img_name:str):
178 | """
179 | Insert the image into the object store and return its object reference
180 | """
181 | import ray
182 |
183 | img = Image.open(img_name)
184 | img_ref = ray.put(img)
185 | return img_ref
186 |
187 | def transform_image(img_ref:object, fetch_image=True, verbose=False):
188 | """
189 | This is a deliberate compute intensive image transfromation and tensor operation
190 | to simulate a compute intensive image processing
191 | """
192 | import ray
193 |
194 | # Only fetch the image from the object store if called serially.
195 | if fetch_image:
196 | img = ray.get(img_ref)
197 | else:
198 | img = img_ref
199 | before_shape = img.size
200 |
201 | # Make the image blur with specified intensify
202 | # Use torchvision transformation to augment the image
203 | img = img.filter(ImageFilter.GaussianBlur(radius=20))
204 | augmentor = T.TrivialAugmentWide(num_magnitude_bins=31)
205 | img = augmentor(img)
206 |
207 | # Convert image to tensor and transpose
208 | tensor = torch.tensor(np.asarray(img))
209 | t_tensor = torch.transpose(tensor, 0, 1)
210 |
211 | # compute intensive operations on tensors
212 | random.seed(42)
213 | for _ in range(3):
214 | tensor.pow(3).sum()
215 | t_tensor.pow(3).sum()
216 | torch.mul(tensor, random.randint(2, 10))
217 | torch.mul(t_tensor, random.randint(2, 10))
218 | torch.mul(tensor, tensor)
219 | torch.mul(t_tensor, t_tensor)
220 |
221 | # Resize to a thumbnail
222 | img.thumbnail(THUMB_SIZE)
223 | after_shape = img.size
224 | if verbose:
225 | print(f"augmented: shape:{img.size}| image tensor shape:{tensor.size()} transpose shape:{t_tensor.size()}")
226 |
227 | return before_shape, after_shape
228 |
229 |
--------------------------------------------------------------------------------