当前位置 : 主页 > 网络安全 > 测试自动化 >

tensorflow – CPU端的性能瓶颈

来源:互联网 收集:自由互联 发布时间:2021-06-22
我正在研究语义分段架构.我需要加快训练速度,但不知道在哪里看得更远. 一般信息 形状的图像(512,512,3) 4 GPU GeForce GTX 1080 11 GB GPU内存可用 1 CPU Intel(R)Xeon(R)CPU E5-2637 v4#3.50GHz可用 足够的
我正在研究语义分段架构.我需要加快训练速度,但不知道在哪里看得更远.

一般信息

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

我尝试了不同的数据加载方法,但每次瓶颈似乎都是CPU而不是GPU.我运行nvidia-smi和htop来查看利用率.

到目前为止我尝试了什么:

> Keras自定义DataGenerator,具有8名工作人员和1个GPU
model.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’))
> Keras tf.data.dataset,数据从tf.Records加载
=>接下来是这个选项.

发现

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

我觉得现在,我的处理链看起来像这样:

磁盘上的数据 – > CPU在RAM中加载数据 – > CPU进行数据预处理 – > CPU将数据移动到GPU – > GPU做了训练步骤

因此,加速培训的唯一方法是预先进行所有预处理并将文件保存到磁盘(数据增加会很大).然后使用tf.Records有效地加载文件.

您是否有其他想法如何提高培训速度?

更新

我用两种型号测试了我的管道.

简单的模型

复杂的模型

表现结果

我为3个时期训练了2个模型,每个模型140个步骤(批量大小= 3).
结果如下.

>原始图像数据=> Keras.DataGenerator
简单型号:126s
复杂模型:154s
>原始图像数据=> tf.data.datasets
简单型号:208s
复杂模型:215s

DataGenerator

辅助功能

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
您的数据处理管道如何完全如此?您是否考虑过省略一些可能过于昂贵的步骤?你的数据是如何存储的?它是按需加载的普通图像文件还是之前已将它们预先加载到内存中?通常加载JPG / PNG图像非常昂贵.

如果在model.fit_generator()中增加max_queue_size,你能看到任何改进吗?

最后,您能否对数据处理管道的实际速度进行基准测试,例如生成几千个批次并计算每批次的时间?

除此之外,我自己的经验是,当您的模型相对较小/计算成本不高时,可能会观察到低GPU利用率.由于新数据必须在批次之间提供给GPU,因此只有一个您无法避免的开销.当此开销与单次通过的实际计算时间之间的比率很高时,您可能会发现您的整体GPU确定性相对较低,甚至经常获得0%的值.

编辑:
您能否向我们提供有关您使用的模型的更多信息,尤其是它主要由哪种层组成.例如,相对较小的CNN的单次通过的计算时间可能太短,以至于通过在批次之间重新供给GPU而不是实际计算来使用更多时间.

更新:
在您添加有关处理管道的更多信息之后,我会说您的主要瓶颈是加载和解码PNG图像. PNG解压缩(甚至压缩甚至更多)通常非常昂贵(根据this源,大约是JPEG的5倍).要检查这个假设,您可以通过确定每个处理步骤(解码,调整大小,裁剪等)需要多少时间以及主要贡献者来分析您的处理流程.

现在有很多方法可以优化您的处理管道:

>您似乎加载了具有不同图像大小的普通,未处理的PNG图像.您至少可以将每个图像文件的大小调整为最终大小.这将节省存储并且应该减少加载/解码开销.>改用JPEG.如果它是“真实世界”的图像,JPEG和PNG之间应该有任何明显的质量差异,但JPEG占用的空间更少,解码成本更低.>如果您有足够的可用存储空间,则可以将整批图像保存为最终格式的压缩Numpy数组.这可能会占用更多空间,但也会大大减少装载时间.

网友评论