<jupyter_start><jupyter_text>Exercise 9 - Using the GPU API**GOAL:** The goal of this exercise is to show how to use GPUs with remote functions and actors.**NOTE:** These exercises are designed to run on a machine without GPUs.See the documentation on using Ray with GPUs http://ray.readthedocs.io/en/latest/using-ray-with-gpus.html. Concepts for this Exercise - Using Ray with GPUsWe can indicate that a remote function or an actor requires some GPUs using the `num_gpus` keyword.```python@ray.remote(num_gpus=1)def f():     The command ray.get_gpu_ids() returns a list of the indices     of the GPUs that this task can use (e.g., [0] or [1]).    ray.get_gpu_ids()@ray.remote(num_gpus=2)class Foo(object):    def __init__(self):         The command ray.get_gpu_ids() returns a list of the         indices of the GPUs that this actor can use         (e.g., [0, 1] or [3, 5]).        ray.get_gpu_ids()```Then inside of the actor constructor and methods, we can get the IDs of the GPUs allocated for that actor with `ray.get_gpu_ids()`.<jupyter_code>from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np
import ray
import time<jupyter_output><empty_output><jupyter_text>Start Ray, note that we pass in `num_gpus=4`. Ray will assume this machine has 4 GPUs (even if it does not). When a task or actor requests a GPU, it will be assigned a GPU ID from the set `[0, 1, 2, 3]`. It is then the responsibility of the task or actor to make sure that it only uses that specific GPU (e.g., by setting the `CUDA_VISIBLE_DEVICES` environment variable).<jupyter_code>ray.init(num_cpus=4, num_gpus=2, redirect_output=True)<jupyter_output>Waiting for redis server at 127.0.0.1:46127 to respond...
Waiting for redis server at 127.0.0.1:55927 to respond...
Warning: Reducing object store memory because /dev/shm has only 66178985984 bytes available. You may be able to free up space by deleting files in /dev/shm. If you are inside a Docker container, you may need to pass an argument with the flag '--shm-size' to 'docker run'.
Starting local scheduler with 4 CPUs, 2 GPUs<jupyter_text>**EXERCISE:** Change the remote function below to require one GPU.**NOTE:** This change does not make the remote function actually **use** the GPU, it simply **reserves** the GPU for use by the remote function. To actually use the GPU, the remote function would use a neural net library like TensorFlow or PyTorch after setting the `CUDA_VISIBLE_DEVICES` environment variable properly. This can be done as follows.```pythonimport osos.environ['CUDA_VISIBLE_DEVICES'] = ','.join([str(i) for i in ray.get_gpu_ids()])```<jupyter_code>@ray.remote(num_gpus=1)
def f():
    time.sleep(0.5)
    return ray.get_gpu_ids()<jupyter_output><empty_output><jupyter_text>**VERIFY:** This code checks that each task was assigned one GPU and that not more than two tasks are run at the same time (because we told Ray there are only two GPUs).<jupyter_code>start_time = time.time()

gpu_ids = ray.get([f.remote() for _ in range(3)])

end_time = time.time()

for i in range(len(gpu_ids)):
    assert len(gpu_ids[i]) == 1

assert end_time - start_time > 1

print('Sucess! The test passed.')<jupyter_output>Sucess! The test passed.<jupyter_text>**EXERCISE:** The code below defines an actor. Make it require one GPU.<jupyter_code>@ray.remote(num_gpus=1)
class Actor(object):
    def __init__(self):
        pass

    def get_gpu_ids(self):
        return ray.get_gpu_ids()<jupyter_output><empty_output><jupyter_text>**VERIFY:** This code checks that the actor was assigned a GPU.<jupyter_code>actor = Actor.remote()

gpu_ids = ray.get(actor.get_gpu_ids.remote())

assert len(gpu_ids) == 1

print('Sucess! The test passed.')<jupyter_output>Sucess! The test passed.
{'fraction_non_alphanumeric': 0.098256735340729, 'fraction_numerical': 0.01584786053882726, 'mean_word_length': 4.6947368421052635, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 3, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '202684', 'license': 'MIT', 'n_tokens_mistral': 1238, 'n_tokens_neox': 1182, 'n_words': 471, 'path': 'exercise09.ipynb', 'repo_name': 'sanzgiri/ray_tutorials', 'size': '3786'}