tensorflow - CPU端的性能瓶颈

标签 tensorflow keras

我正在研究语义分割架构。我需要加快训练速度,但不知道该往哪里看。
一般信息

  • 形状的图像 (512,512,3)
  • 4 GPU GeForce GTX 1080 11 GB GPU 内存可用
  • 1 CPU Intel(R) Xeon(R) CPU E5-2637 v4 #3.50GHz 可用
  • 足够的内存
  • 我使用 Keras
  • 我用的是轻数据预处理(主要是裁剪,数据增强不多)

  • 我尝试了不同的数据加载方法,但每次瓶颈似乎都是 CPU 而不是 GPU。我跑 nvidia-smihtop看利用率。
    到目前为止我尝试过的:
  • Keras + 带有 8 个工作器和 1 个 GPU 的自定义 DataGeneratormodel.fit_generator(generator=training_generator,use_multiprocessing=True, workers=8)
  • Keras + tf.data.dataset 带有从原始图像加载的数据model.fit(training_dataset.make_one_shot_iterator(),...) 我尝试了两种预取方式:dataset = dataset.prefetch(tf.contrib.data.AUTOTUNE)dataset = dataset.apply(tf.contrib.data.prefetch_to_device('/gpu:0'))
  • 从 tf.Records 加载数据的 Keras + tf.data.dataset
    => 接下来是这个选项。

  • 发现
  • 使用多个 GPU(用 Keras 很容易做到)会减慢训练速度,因为开销计算会占用 CPU。
  • 令人惊讶的是,普通的 DataGenerator 方法(没有 tf.data.dataset)现在是最快的。
  • 每种方法的 GPU 利用率都会在很短的时间内达到 100%。但有时也是 0%。

  • 我觉得现在,我的处理链是这样的:
    磁盘上的数据 -> CPU 在 RAM 中加载数据 -> CPU 进行数据预处理 -> CPU 将数据移动到 GPU -> GPU 进行训练步骤
    因此,加快训练速度的唯一方法是预先进行所有预处理并将文件保存到磁盘(数据增强会很大)。然后使用 tf.Records 高效加载文件。
    您有其他想法如何提高训练速度吗?
    更新
    我已经用两个模型测试了我的管道。
    简单模型
    enter image description here
    复杂模型
    enter image description here
    性能结果
    我为 3 个 epoch 训练了 2 个模型,每个模型有 140 个步骤(批量大小 = 3)。
    这是结果。
  • 原始图像数据 => Keras.DataGenerator
    简单模型:126s
    复杂模型:154s
  • 原始图像数据 => tf.data.datasets
    简单型号:208s
    复杂模型:215s

  • 数据生成器
    辅助功能
    def load_image(self,path):
        image = cv2.cvtColor(cv2.imread(path,-1), cv2.COLOR_BGR2RGB)
        return image
    
    主要部分
    #Collect a batch of images on the CPU step by step (probably the bottlebeck of the whole computation)
    for i in range(len(image_filenames_tmp)):
        #print(image_filenames_tmp[i])
        #print(label_filenames_tmp[i])
        input_image = self.load_image(image_filenames_tmp[i])[: self.shape[0], : self.shape[1]]
        output_image = self.load_image(label_filenames_tmp[i])[: self.shape[0], : self.shape[1]]
    
        # Prep the data. Make sure the labels are in one-hot format
        input_image = np.float32(input_image) / 255.0
        output_image = np.float32(self.one_hot_it(label=output_image, label_values=label_values))
            
        input_image_batch.append(np.expand_dims(input_image, axis=0))
        output_image_batch.append(np.expand_dims(output_image, axis=0))
    
        input_image_batch = np.squeeze(np.stack(input_image_batch, axis=1))
        output_image_batch = np.squeeze(np.stack(output_image_batch, axis=1))            
        
        
    return input_image_batch, output_image_batch
    
    tf.data.dataset
    辅助功能
    def preprocess_fn(train_image_filename, train_label_filename):
    '''A transformation function to preprocess raw data
    into trainable input. '''
         x = tf.image.decode_png(tf.read_file(train_image_filename))
         x = tf.image.convert_image_dtype(x,tf.float32,saturate=False,name=None)
        
         x = tf.image.resize_image_with_crop_or_pad(x,512,512)
                
         y = tf.image.decode_png(tf.read_file(train_label_filename))
         y = tf.image.resize_image_with_crop_or_pad(y,512,512)
                
         class_names, label_values = get_label_info(csv_path)
                
         semantic_map = []
         for colour in label_values:
             class_map = tf.reduce_all(tf.equal(y, colour), axis=-1)
             semantic_map.append(class_map)
             semantic_map = tf.stack(semantic_map, axis=-1)
             # NOTE cast to tf.float32 because most neural networks operate in float32.
          semantic_map = tf.cast(semantic_map, tf.float32)       
        
          return x, semantic_map
        
    
    主要部分
    dataset = tf.data.Dataset.from_tensor_slices((train_image_filenames, train_label_filenames))
    
    dataset = dataset.apply(tf.contrib.data.map_and_batch(
                preprocess_fn, batch_size,
                num_parallel_batches=4,  # cpu cores
                drop_remainder=True if is_training    
    dataset = dataset.repeat()
    dataset = dataset.prefetch(tf.contrib.data.AUTOTUNE) # automatically picks best buffer_size
        
    

    最佳答案

    我正在处理类似的问题,尝试优化管道是一场艰苦的战斗。
    使用 horovod 而不是 keras multi-gpu 给我带来了几乎线性的加速,而 keras multi-gpu 没有:
    https://medium.com/omnius/keras-horovod-distributed-deep-learning-on-steroids-94666e16673d

    tf.dataset 绝对是要走的路。您可能还想进行 shuffle 操作以获得更好的泛化。

    另一件对我来说有很大改善的事情是预先调整图像大小并使用 np.save() 将它们保存为 .npy 文件。它们需要更多的空间来保存,但读取它们的速度要快一个数量级。我使用 tf.py_func() 将我的 numpy 操作转换为张量(由于 python GIL 无法并行化)

    Nvidia 最近发布了 DALI。它在 GPU 上进行了增强,这绝对是 future 的发展方向。对于简单的分类任务,它可能已经具备您需要的所有功能。

    关于tensorflow - CPU端的性能瓶颈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51260680/

    相关文章:

    tensorflow - 如何安装tensorflow==2.3.0

    tensorflow - 如何使用tensor2tensor对文本进行分类?

    python - 在循环中构建图形时 Tensorflow 内存泄漏

    python - 在anaconda 5.3中安装tensorflow gpu

    python - Keras LSTM 自动编码器时间序列重建

    python - 从 [tensorflow 1.00] 中的 softmax 层提取概率

    python - Keras 密集层输出形状

    python - tensorflow 回归神经网络对所有内容输出相同的数字

    python - key 错误 : "Unable to open object (object ' imgs' doesn't exist)"

    python - 我们如何在 Keras 中创建一个 block (可重用的函数集)?