【问题标题】:Slow training on CPU and GPU in a small network (tensorflow)小型网络中 CPU 和 GPU 的慢速训练(tensorflow)
【发布时间】:2020-12-08 10:13:01
【问题描述】:

这是原始的script 我正在尝试在 CPU 和 GPU 上运行,我希望在 GPU 上进行更快的训练,但它几乎需要相同的时间。我对main()(前4行)进行了以下修改,因为原始脚本没有激活/使用GPU。建议...?

def main():
    physical_devices = tf.config.experimental.list_physical_devices('GPU')
    if len(physical_devices) > 0:
        tf.config.experimental.set_memory_growth(physical_devices[0], True)
        print('GPU activated')
    env = gym.make('CartPole-v1')
    agent = Agent(env)
    agent.train(max_episodes=1000)

更新:

wandb 的 report 显示 GPU 利用率为 0%,这表明存在问题

有问题的完整代码不是我的,属于这个repository

import wandb
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.optimizers import Adam

import gym
import argparse
import numpy as np
from collections import deque
import random

tf.keras.backend.set_floatx('float64')
wandb.init(name='DQN', project="deep-rl-tf2")

parser = argparse.ArgumentParser()
parser.add_argument('--gamma', type=float, default=0.95)
parser.add_argument('--lr', type=float, default=0.005)
parser.add_argument('--batch_size', type=int, default=32)
parser.add_argument('--eps', type=float, default=1.0)
parser.add_argument('--eps_decay', type=float, default=0.995)
parser.add_argument('--eps_min', type=float, default=0.01)

args = parser.parse_args()

class ReplayBuffer:
    def __init__(self, capacity=10000):
        self.buffer = deque(maxlen=capacity)
    
    def put(self, state, action, reward, next_state, done):
        self.buffer.append([state, action, reward, next_state, done])
    
    def sample(self):
        sample = random.sample(self.buffer, args.batch_size)
        states, actions, rewards, next_states, done = map(np.asarray, zip(*sample))
        states = np.array(states).reshape(args.batch_size, -1)
        next_states = np.array(next_states).reshape(args.batch_size, -1)
        return states, actions, rewards, next_states, done
    
    def size(self):
        return len(self.buffer)

class ActionStateModel:
    def __init__(self, state_dim, aciton_dim):
        self.state_dim  = state_dim
        self.action_dim = aciton_dim
        self.epsilon = args.eps
        
        self.model = self.create_model()
    
    def create_model(self):
        model = tf.keras.Sequential([
            Input((self.state_dim,)),
            Dense(32, activation='relu'),
            Dense(16, activation='relu'),
            Dense(self.action_dim)
        ])
        model.compile(loss='mse', optimizer=Adam(args.lr))
        return model
    
    def predict(self, state):
        return self.model.predict(state)
    
    def get_action(self, state):
        state = np.reshape(state, [1, self.state_dim])
        self.epsilon *= args.eps_decay
        self.epsilon = max(self.epsilon, args.eps_min)
        q_value = self.predict(state)[0]
        if np.random.random() < self.epsilon:
            return random.randint(0, self.action_dim-1)
        return np.argmax(q_value)

    def train(self, states, targets):
        self.model.fit(states, targets, epochs=1, verbose=0)
    

class Agent:
    def __init__(self, env):
        self.env = env
        self.state_dim = self.env.observation_space.shape[0]
        self.action_dim = self.env.action_space.n

        self.model = ActionStateModel(self.state_dim, self.action_dim)
        self.target_model = ActionStateModel(self.state_dim, self.action_dim)
        self.target_update()

        self.buffer = ReplayBuffer()

    def target_update(self):
        weights = self.model.model.get_weights()
        self.target_model.model.set_weights(weights)
    
    def replay(self):
        for _ in range(10):
            states, actions, rewards, next_states, done = self.buffer.sample()
            targets = self.target_model.predict(states)
            next_q_values = self.target_model.predict(next_states).max(axis=1)
            targets[range(args.batch_size), actions] = rewards + (1-done) * next_q_values * args.gamma
            self.model.train(states, targets)
    
    def train(self, max_episodes=1000):
        for ep in range(max_episodes):
            done, total_reward = False, 0
            state = self.env.reset()
            while not done:
                action = self.model.get_action(state)
                next_state, reward, done, _ = self.env.step(action)
                self.buffer.put(state, action, reward*0.01, next_state, done)
                total_reward += reward
                state = next_state
            if self.buffer.size() >= args.batch_size:
                self.replay()
            self.target_update()
            print('EP{} EpisodeReward={}'.format(ep, total_reward))
            wandb.log({'Reward': total_reward})


def main():
    env = gym.make('CartPole-v1')
    agent = Agent(env)
    agent.train(max_episodes=1000)

if __name__ == "__main__":
    main()

【问题讨论】:

  • GPU 与 CPU 相比需要多长时间?
  • @Robert Young 我没有计算确切的时间,因为它可能会运行几个小时,我只是在我的 2015 i5 mbp 上运行它,然后在 google colab 上运行它,并通过比较本地版本与colab 版本,每个屏幕都以几乎相同的速度显示进度
  • 请不要链接到站外代码。当有人在 5(或 10 或 20)年后阅读此问题时,谁知道链接的存储库(或 GitHub,就此而言!)在哪里。

标签: python tensorflow2.0 reinforcement-learning custom-training


【解决方案1】:

我非常怀疑 I/O 操作几乎占用了所有内容(尤其是您自行实现的重放缓冲区)。要检查这一点,我建议使用TF-profiler;为此,请尝试these 方法之一。 Youtube 上还有一些非常有用的视频,介绍了如果您有任何其他问题,如何使用分析器。

至于加速代码的可能优化,我强烈建议迁移到 TF-Agents 框架,其中代理、重放缓冲区和 ecc。已经以有效的方式预先实施。了解它有点学习曲线,但对于 RL 来说非常值得

【讨论】:

  • 这不是我的代码,你是对的,IO 操作肯定占用了大部分时间,但 GPU 利用率为 0%?这有点出乎意料。我正在使用此代码和其他几个版本来熟悉 DRL 算法(尽可能少地担心实现细节),因为该主题相对较新,因此没有合适的课程可用。一旦我了解了不同 DRL 算法的内部工作原理,如果它们足够灵活,可以与其他代理异步自定义/使用,我可能会切换到 tensorflow 代理。我会检查 tf-profiler,谢谢。
猜你喜欢
  • 2017-03-30
  • 1970-01-01
  • 2017-06-25
  • 2019-09-09
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多