2017-05-30 2 views
7

Ich arbeite mit tensorflow und ich mag die Vorhersage Phase eines vortrainiert Keras Modells beschleunigen (Ich bin in der Trainingsphase nicht interessiert) von gleichzeitig mit die CPU und eine GPU.Tensorflow: gleichzeitige Vorhersage auf GPU und CPU

Ich habe versucht, 2 verschiedene Threads zu erstellen, die zwei verschiedene Tensorflow-Sitzungen (eine, die auf der CPU und die andere, die auf GPU ausgeführt wird) führen. Jeder Thread füttert eine feste Anzahl von Batches (z. B. wenn wir insgesamt 100 Batches haben, möchte ich 20 Batches für CPU und 80 für GPU zuweisen, oder jede mögliche Kombination der beiden) in einer Schleife und kombiniere das Ergebnis. Es wäre besser, wenn die Aufteilung automatisch erfolgt.

Aber selbst in diesem Szenario scheint es, dass die Chargen auf eine synchrone Art und Weise gefüttert werden, weil sogar einige Chargen an die CPU gesendet und alle anderen in der GPU (mit der GPU als Flaschenhals) berechnet wurden Die Gesamtvorhersagezeit ist immer höher in Bezug auf den Test, der nur unter Verwendung der GPU durchgeführt wird.

Ich würde erwarten, dass es schneller sein wird, denn wenn nur die GPU arbeitet, ist die CPU-Auslastung etwa 20-30%, daher ist etwas CPU verfügbar, um die Berechnung zu beschleunigen.

Ich lese viele Diskussionen, aber sie alle befassen sich mit Parallelität mit mehreren GPUs und nicht zwischen GPU und CPU. Hier

ist ein Beispiel für den Code habe ich geschrieben: die tensor_cpu und tensor_gpu Objekte aus dem gleichen Keras Modell auf diese Weise geladen:

with tf.device('/gpu:0'): 
    model_gpu = load_model('model1.h5') 
    tensor_gpu = model_gpu(x) 

with tf.device('/cpu:0'): 
    model_cpu = load_model('model1.h5') 
    tensor_cpu = model_cpu(x) 

Dann ist die Vorhersage, wie folgend getan wird:

def predict_on_device(session, predict_tensor, batches): 
    for batch in batches: 
     session.run(predict_tensor, feed_dict={x: batch}) 


def split_cpu_gpu(batches, num_batches_cpu, tensor_cpu, tensor_gpu): 
    session1 = tf.Session(config=tf.ConfigProto(log_device_placement=True)) 
    session1.run(tf.global_variables_initializer()) 
    session2 = tf.Session(config=tf.ConfigProto(log_device_placement=True)) 
    session2.run(tf.global_variables_initializer()) 

    coord = tf.train.Coordinator() 

    t_cpu = Thread(target=predict_on_device, args=(session1, tensor_cpu, batches[:num_batches_cpu])) 
    t_gpu = Thread(target=predict_on_device, args=(session2, tensor_gpu, batches[num_batches_cpu:])) 

    t_cpu.start() 
    t_gpu.start() 

    coord.join([t_cpu, t_gpu]) 

    session1.close() 
    session2.close() 

Wie kann ich diese CPU/GPU-Parallelisierung erreichen? Ich denke, ich vermisse etwas.

Jede Art von Hilfe wäre sehr willkommen!

+0

Habe ich Ihre Frage beantwortet? – MaxB

+0

Ja, ja, ja !! Es tut mir leid für die späte Antwort, ich war mit einem anderen Projekt beschäftigt und ich hatte keine Zeit, das auszuprobieren. Ich habe Ihren Code überprüft .. könnte es sein, dass der einzige Grund, warum es nicht funktioniert hat, die Option intra_op_parallelism_thread? – battuzz

+0

Irgendeine Idee, wie ich Tensorflow finden kann, die richtige Menge von Chargen zu CPU und GPU zu füttern, so dass ich die gesamte Vorhersagezeit minimieren kann? – battuzz

Antwort

3

Hier ist mein Code, der, wie die Ausführung der CPU und GPU zeigt, können parallel durchgeführt werden:

import tensorflow as tf 
import numpy as np 
from time import time 
from threading import Thread 

n = 1024 * 8 

data_cpu = np.random.uniform(size=[n//16, n]).astype(np.float32) 
data_gpu = np.random.uniform(size=[n , n]).astype(np.float32) 

with tf.device('/cpu:0'): 
    x = tf.placeholder(name='x', dtype=tf.float32) 

def get_var(name): 
    return tf.get_variable(name, shape=[n, n]) 

def op(name): 
    w = get_var(name) 
    y = x 
    for _ in range(8): 
     y = tf.matmul(y, w) 
    return y 

with tf.device('/cpu:0'): 
    cpu = op('w_cpu') 

with tf.device('/gpu:0'): 
    gpu = op('w_gpu') 

def f(session, y, data): 
    return session.run(y, feed_dict={x : data}) 


with tf.Session(config=tf.ConfigProto(log_device_placement=True, intra_op_parallelism_threads=8)) as sess: 
    sess.run(tf.global_variables_initializer()) 

    coord = tf.train.Coordinator() 

    threads = [] 

    # comment out 0 or 1 of the following 2 lines: 
    threads += [Thread(target=f, args=(sess, cpu, data_cpu))] 
    threads += [Thread(target=f, args=(sess, gpu, data_gpu))] 

    t0 = time() 

    for t in threads: 
     t.start() 

    coord.join(threads) 

    t1 = time() 


print t1 - t0 

Die Timing Ergebnisse sind:

  • CPU thread: 4-5s maschinell (variiert , Na sicher).

  • GPU-Thread: 5s (Es tut 16x so viel Arbeit).

  • Beide zugleich: 5s

Beachten Sie, dass es keine Notwendigkeit, 2 Sitzungen haben war (aber das auch für mich gearbeitet hat).

Die Gründe könnten Sie unterschiedliche Ergebnisse sehen werden

  • einige Rennen um Systemressourcen Ausführung (GPU könnte einige Host-Systemressourcen verbraucht, und die CPU-Thread, wenn es läuft massen, das könnte die Leistung verschlechtern)

  • falsche Timing

  • Ihres Modells Teil nur auf GPU/CPU laufen kann

  • Engpass an anderer Stelle

  • ein anderes Problem