zoukankan      html  css  js  c++  java
  • [tf] tensorflow中multi-GPU小坑记录

    tensorflow中multi-GPU小坑记录

    最近又需要点tf的代码,有几个点关于多卡的代码点需要记录下。一直想把平时常用的一些代码段整理一下,但是一直没时间,每周有在开新的进程,找时间再说吧。先零星的记点吧。

    干货

    1. 在tf构图阶段,把计算点都开在GPU上,尽量不要开在CPU上。提速杠杠滴!
    2. 在多卡读取数据阶段,在for len(num_gpu)循环外建立queue,在循环内取数据。

    好了,主要的干货就没有了,看懂的可以ctrl+w了。
    不太了解的,咱继续。

    tf构图在GPU上

    1. 在tf构图阶段,把计算点都开在GPU上,尽量不要开在CPU上。提速杠杠滴!
    with tf.Graph().as_default(), tf.device('/gpu:0'):
    	y = interface(x)
    	...
    	with tf.Session(config = tf.ConfigProto(log_device_placement=True,allow_soft_placement=True)) as sess:
    		sess.run(...)
    

    在train function中构静态图时,把节点和运算都放在GPU上,同时需要加上allow_soft_placement=True,这个flag的作用是保证程序能正常运行,因为有些运算操作是不能放在GPU上运行的,flag保证了那些操作会转移到CPU上运行。

    result

    单卡os.environ["CUDA_VISIBLE_DEVICES"] = "0"跑的数据,不做严谨定量展现,只定量的感受下提速。CPU上
    113s per 100 batch_size,转到GPU上后提速到11s。

    CPU

    GPU

    4卡上跑实验,per 100 batch_size,CPU:295s,GPU:65s。

    CPU

    GPU

    multiGPU读取数据

    目前在r1.2的版本上用的还是queue的方式,好像在r1.4版本上官方推荐使用Dataset API,暂时还没有切版本。

    2.在多卡读取数据阶段,在for len(num_gpu)循环外建立queue,在循环内取数据。

    def get_input(self,data_path_list,batch_size):
    	file_list = os.listdir(data_path_list)
    	file_list = [data_path_list+'/'+ i for i in file_list]
    	with tf.variable_scope("tfrecords_input"):
    		filename_queue = tf.train.string_input_producer(file_list)
    		reader = tf.TFRecordReader()
    		_,serialized_example = reader.read(filename_queue)
    		# 解析单个数据格式
    		features = tf.parse_single_example(serialized_example,
    									   features={
    										   'x':tf.FixedLenFeature([],tf.string),
    										   'labels':tf.FixedLenFeature([],tf.string)
    									   })  
    		x = tf.reshape(tf.decode_raw(features['x'],tf.int32),[2,self.n_features])
    		labels = tf.reshape(tf.decode_raw(features['labels'],tf.int32), [1,2])
    		return x, labels
    		
    def train():
    	min_after_dequeue = 1000
    	capacity = min_after_dequeue+4*batch_size
    	x_, labels = get_input(train_tfrecords_path,batch_size)
    	with tf.variable_scope(tf.get_variable_scope()): 
    		for i in range(num_gpus):
    			with tf.device('gpu:%d' % i): 
    				with tf.name_scope('GPU_%d' % i) as scope:
    					train_data = tf.train.shuffle_batch([x_,labels],
    												  batch_size=batch_size,
    												  capacity=capacity,
    												  min_after_dequeue=min_after_dequeue,
    												  num_threads=3)
    					x =  train_data[0]
    					y_ = train_data[-1]
    					interface_output = interface(x)
    					cur_loss = compute_loss(interface_output,y_,reg=None)
    					...
    

    最初是把tf.train.shuffle_batch这步放在了for循环的外边,紧跟着get_input()函数,但是发现这样的话读取出来的是同一个batch_size的数据。

    haha

    写tf的时候还是记得转变下思维,不能总是按照C++的方式觉得每一步都会有定值,tf在没有sess.run之前只是个占位符而已,并没有数据流动!!!

  • 相关阅读:
    java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header.
    spring-session-data-redis依赖冲突问题
    centos7启动iptables时报Job for iptables.service failed because the control process exited with error cod
    图片上传后台服务报内存溢出 Out Of Memory Java heap space
    mysql 数据库密码忘记重置 进行远程连接
    打Jar包
    Type interface com.innovationV2.mapper.UserMapper is not known to the MapperRegistry
    关于java基础类型Integer String的clone()
    clion使用clang编译
    token & refresh token 机制总结
  • 原文地址:https://www.cnblogs.com/zhanxiage1994/p/7989340.html
Copyright © 2011-2022 走看看