tensorflow Ray:如何在一个GPU上运行多个演员?

yvfmudvl  于 2023-10-23  发布在  其他
关注(0)|答案(2)|浏览(147)

我只有一个gpu,我想在这个gpu上运行许多角色。下面是我在https://ray.readthedocs.io/en/latest/actors.html之后使用ray所做的事情
1.首先在gpu上定义网络

class Network():
    def __init__(self, ***some args here***):
        self._graph = tf.Graph()
        os.environ['CUDA_VISIBLE_DIVICES'] = ','.join([str(i) for i in ray.get_gpu_ids()])
        with self._graph.as_default():
            with tf.device('/gpu:0'):
                # network, loss, and optimizer are defined here

        sess_config = tf.ConfigProto(allow_soft_placement=True)
        sess_config.gpu_options.allow_growth=True
        self.sess = tf.Session(graph=self._graph, config=sess_config)
        self.sess.run(tf.global_variables_initializer())
        atexit.register(self.sess.close)

        self.variables = ray.experimental.TensorFlowVariables(self.loss, self.sess)

1.然后定义工人类

@ray.remote(num_gpus=1)
class Worker(Network):
    # do something

1.定义学习者类

@ray.remote(num_gpus=1)
class Learner(Network):
    # do something

1.列车功能

def train():
    ray.init(num_gpus=1)
    leaner = Learner.remote(...)
    workers = [Worker.remote(...) for i in range(10)]
    # do something

这个过程工作正常,当我不试图使它在gpu上工作。也就是说,当我删除所有with tf.device('/gpu:0')(num_gpus=1)时,它工作得很好。当我保留它们时,麻烦就来了:似乎只创建了learner,但没有构建任何workers。我该怎么做才能让它工作?

ee7vknir

ee7vknir1#

当您使用装饰器@ray.remote(num_gpus=1)定义一个actor类时,您是在说从这个类创建的任何actor都必须在其生命周期内为其保留一个GPU。由于您只有一个GPU,因此只能创建一个这样的actor。
如果你想让多个演员共享一个GPU,那么你需要指定每个演员需要少于1个GPU,例如,如果你想在4个演员之间共享一个GPU,那么你可以让每个演员需要1/4的GPU。这可以通过使用

@ray.remote(num_gpus=0.25)

此外,你需要确保每个参与者都真正尊重你对它的限制。例如,如果你想用@ray.remote(num_gpus=0.25)声明一个actor,那么你还应该确保TensorFlow最多使用四分之一的GPU内存。例如,请参阅How to prevent tensorflow from allocating the totality of a GPU memory?的答案。

68bkxrlz

68bkxrlz2#

如果有人想在多GPU系统上运行Ray并重新运行TensorFlow功能,可以按如下方式解决这个问题。假设你有2个GPU,想要运行16个actor。

  1. init ray和为每个物理GPU配置内存增长:
physical_gpus = tf.config.list_physical_devices("GPU")
# set memory growth for each visible GPU
for device in physical_gpus:
    tf.config.experimental.set_memory_growth(device, True)
num_gpus = len(physical_gpus)
ray.init(num_gpus=num_gpus)

1.计算要使用的部分GPU,gpu_share_per_task:

total_tasks = number_of_parallel_tasks_
divider = total_tasks // num_gpus
if total_tasks % num_gpus > 0:
    divider += 1
    gpu_share_per_task = 1 / divider

1.定义演员并用ray.remote(num_gpus=gpu_share_per_task)装饰:

@ray.remote(num_gpus=gpu_share_per_task)
    class Simulator:
        def __init__(self, i, *args, **kwargs):
            # do init

        def simulate(
            self,
        ):
            # check the ray logical GPU assigned, it will be in the range [0, 15]
            gpu_id = ray.get_gpu_ids()[0]
            print("gpu_id:", gpu_id)
            # IMPORTANT: make sure to either set_memory_growth or set memory limit for each actor!
            # Otherwise, tf will occupy all of the GPU memory.
            # e.g.:
            physical_gpus = tf.config.list_physical_devices("GPU")
            for gpu in physical_gpus:
                tf.config.set_logical_device_configuration(
                    gpu,
                    [tf.config.LogicalDeviceConfiguration(memory_limit=2048)],
        )
            # do the tf magic you want
            # ...

1.创建并运行Actor:

# Create actors
    simulators = [Simulator.remote(i, args, kwargs) for i in range(16)]
    
    # Run simulations in parallel
    results = ray.get([s.simulate.remote() for s in simulators])

两个GPU都将被利用,演员将运行GPU。
这个设置适用于我的TensorFlow 2.10.1和Ray 2.6.1。

相关问题