2016-11-03 5 views
3

두 개의 gpu (TitanX (Pascal) 및 GTX 1080)가 있습니다. 단일 스레드 그래프 계산을 실행하려면 을 시도하고 있습니다. 그래프는 두 개의 별도 매트릭스 곱셈 체인 (각각 해당 GPU에 할당 됨)입니다. 여기 TensorFlow 2gpu보다 느린 단일 gpu

내가 사용하고 코드입니다 :

수입 tensorflow를 NP 수입 임의 수입 시간 수입 로깅과 같은 수입 NumPy와 TF대로 20.4 초 소요

from tensorflow.python.ops import init_ops 
from tensorflow.python.client import timeline 


def test(): 
    n = 5000 

    with tf.Graph().as_default(): 
     A1 = tf.placeholder(tf.float32, shape=[n, n], name='A') 
     A2 = tf.placeholder(tf.float32, shape=[n, n], name='A') 
     with tf.device('/gpu:0'): 
      B1 = A1 
      for l in xrange(10): 
       B1 = tf.matmul(B1, A1) 

     with tf.device('/gpu:1'): 
      B2 = A2 
      for l in xrange(10): 
       B2 = tf.matmul(B2, A2) 
      C = tf.matmul(B1, B2) 

     run_metadata = tf.RunMetadata() 
     with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess: 
      start = time.time() 
      logging.info('started') 
      A1_ = np.random.rand(n, n) 
      A2_ = np.random.rand(n, n) 
      sess.run([C], 
        feed_dict={A1: A1_, A2: A2_}, 
        options=tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE), 
        run_metadata=run_metadata) 
      logging.info('writing trace') 
      trace = timeline.Timeline(step_stats=run_metadata.step_stats) 
      trace_file = open('timeline.ctf.json', 'w') 
      trace_file.write(trace.generate_chrome_trace_format()) 
      logging.info('trace written') 
      end = time.time() 
      logging.info('computed') 
      logging.info(end - start) 


if __name__ == "__main__": 
    logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') 
    test() 
  • 끝.
  • 모든 작업을 gpu0 (TitanX)으로 설정하면 14 초가 걸립니다.
  • 모든 작업을 gpu1 (GTX 1080)로 설정하면 19.8 초가 걸립니다.

나는 tensorflow가 gpus를 발견했으며 모든 장치를 올바르게 설정했음을 알 수 있습니다. 왜 2 GPU 대신 하나의 속도를 최대 속도가 있습니까? 문제는 gpus가 다른 모델 (AFAIK cuda가 허용)일까요?

감사합니다. 그렇지 않으면 tensorflow 몇 가지 최적화를 할 것으로 보인다 이후

편집 I 업데이트 된 코드는 모두 체인에 대해 서로 다른 초기 행렬을 사용합니다. https://api.myjson.com/bins/23csi

Screenshot

이 타임 라인이 답변보다 더 많은 질문을 제기 : 여기

타임 라인 프로파일 JSON 파일 링크입니다

PID 7 (gpu0이) 실행의 두 선이 왜
  1. ?
  2. pid 3 및 5의 긴 MatMuls는 무엇입니까?
  3. 모든 영업 이익은 작은 많이 있습니다 5.
  4. gpu0의 execept의 PID에서 실행되는 것으로 보인다 ("_recv_A_0/_3"이름 "MatMul"OP "MatMul"입력 1 "_recv_A_0/_3"input0) MatMul 운영체제 (스크린 샷에서 볼 수 없음)는 pid 3과 pid 5의 MatMuls 작업이 끝난 직후입니다.
+0

당신은'sess.run을 할 수 병목 https://github.com/tensorflow/tensorflow/issues/1824#issuecomment-225754659 –

+0

은 또한 무엇을 볼 수있는 타임 라인을 볼 수 있습니다 (C.op),'sess.run (C)'대신 TensorFlow-> Python이 –

+0

에서 발생했습니다. "TypeError : __init __()가 세션 생성자에서 예상치 못한 키워드 인자 'run_metadata'를 얻었습니다. 9 월 16 일에 소스를 가져 와서 pip에서 다시 설치하려고했는데 (여전히 같은 오류가 발생했습니다.) – MikleB

답변

2

GPU에서 처음으로 커널을 시작할 때 PTXAS 컴파일로 인해 지연 될 수 있습니다. 이 지연 시간은 초 단위 일 수 있으며 GPU가 2 개 이상일 때 누적됩니다. 따라서 "초기 커널 시작"이 추가로 시간을 차지하기 때문에 실행 속도가 느려집니다. 순수 계산 시간을 벤치 마크하는 한 가지 방법은 각 GPU에서 적어도 한 번씩 각 cuda 작업을 실행하여 "예열"하는 것입니다. 두 TitanX 카드에서 벤치 마크를 실행하여 같은 속도 저하를 보았습니다. 그러나 커널을 "예열"했을 때이 지연이 사라졌습니다.여기 enter image description here

사전 온난화 후입니다 :

여기에 사전 온난화 전에의 enter image description here 아래는 어떤 TensorFlow < 제거도 사전 온난화를 수행하고 수정 된 코드입니다 -> 파이썬 전송을.

import tensorflow as tf 

from tensorflow.python.ops import init_ops 
from tensorflow.python.client import timeline 
import logging, time 
import numpy as np 

def test(): 
    n = 5000 

    with tf.device('/gpu:0'): 
     A1 = tf.Variable(tf.ones_initializer(shape=[n, n]), name='A1') 
     B1 = A1 
     for l in xrange(10): 
      B1 = tf.matmul(A1, B1, name="chain1") 

    with tf.device('/gpu:1'): 
     A2 = tf.Variable(tf.ones_initializer(shape=[n, n]), name='A2') 
     B2 = A2 
     for l in xrange(10): 
      B2 = tf.matmul(A2, B2, name="chain2") 
     C = tf.matmul(B1, B2) 

    run_metadata = tf.RunMetadata() 
    start = time.time() 
    logging.info('started') 
    sess = tf.InteractiveSession(config=tf.ConfigProto(allow_soft_placement=False, log_device_placement=True)) 
    sess.run(tf.initialize_all_variables()) 
    # do warm-run 
    sess.run([C.op], 
      options=tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE), 
      run_metadata=run_metadata) 
    run_metadata = tf.RunMetadata() 
    sess.run([C.op], 
      options=tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE), 
      run_metadata=run_metadata) 
    logging.info('writing trace') 
    trace = timeline.Timeline(step_stats=run_metadata.step_stats) 
    trace_file = open('timeline.ctf.json', 'w') 
    trace_file.write(trace.generate_chrome_trace_format(show_memory=True)) 
    logging.info('trace written') 
    end = time.time() 
    logging.info('computed') 
    logging.info(end - start) 


if __name__ == "__main__": 
    logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') 
    test() 
+0

btw, 레이블은 오해의 소지가있는 "gpu : 0/stream : 22"타임 라인에서 실제로 gpu : 1에 있으며, log_device_placement에서 볼 수 있습니다. –

+0

설명해 주셔서 감사합니다. 그러나 이러한 타임 라인 추적은 여전히 ​​이상하게 보입니다. 왜 모든 연산을 gpu0에 대입하면 결과는 항상 계산됩니다 (다른 행렬 크기를 5000에서 20000으로 시도하고 서로 다른 체인 길이를 최대 100으로 시도 했습니까?). 이 두 체인은 단일 GPU에서도 두 개의 병렬 스트림으로 계산 될 수 있습니다. – MikleB

+0

맞습니다. tensorflow는 병렬 스트림에서 연산을 예약하지 않고 대신 각 연산이 GPU의 모든 스트림을 사용할 수 있습니다 –

0

C을 계산할 때 GPU간에 데이터를 전송해야하나요? C을 cpu에 넣을 수 있습니까?

with tf.device('/cpu:0'): 
    C = tf.matmul(B1, B2) 
+0

도움이되지 않습니다. 또한 내가 마지막으로하기 전에 각각의 GPU에 500 매트릭스 릿츠가 있기 때문에 중요하지 않아야한다고 생각합니다. – MikleB

관련 문제