2017-01-07 69 views
2

我對tensorflow用於爲CPU或GPU分配不同Ops的機制感到困惑。tensorflow如何分配Ops在GPU上運行?

  1. 以下面的僞代碼爲例。我們可以說:只要SimpleOp是 的with tf.device('/gpu:0')範圍內創建的,它會 肯定在GPU上運行(假設的SimpleOp 是可用的GPU實現),不管其輸入變量(in_1in_2)在CPU或GPU上創建了 ?

    with tf.device('/gpu:0'): 
        out = tf.SimpleOp(in_1, in_2, name='Simple') 
    
  2. 餘通過與 log_device_placement=True,tensorflow輸出裝置中的所有變量/業務的 刊登位置創建session理解。但是,有沒有一種方法允許我只檢查一個Op的設備分配?

在此先感謝!

回答

5

TLDR;在with tf.device("/gpu:0")中創建的操作將始終在GPU上運行。如果您指定輸入放置在cpu上,則它們將被放置在CPU上。如果您省略了輸入的設備規格,則它們將放置在GPU上以更接近您的操作。您可以使用run_metadata來獲取包含所有設備分配的Python對象,並在那裏查找您的操作。

安置是通過誤導性地命名爲simple_placer.cc完成的,雖然註釋指定了機制,但仍有一些錯誤被散列(即,here),所以最好的方法是在實踐中檢查它。

當你說在GPU上創建變量時,實際上有兩種放置方式 - 明確的,當你在with tf.device塊內創建相關操作時,以及隱含的,在這種塊之外。在with tf.device之外創建操作等同於在with tf.device(None)塊中創建操作。

所以這裏有一個簡單的實驗

n = 10**6 
def inputs_cpu(): 
    tf.reset_default_graph() 
    with tf.device("/cpu:0"): 
     a = tf.ones((n,), name="A") 
     b = tf.ones((n,), name="B") 
    with tf.device("/gpu:0"): 
     c = tf.add(a, b, name="C") 
    return c 

def inputs_none(): 
    tf.reset_default_graph() 
    a = tf.ones((n,), name="A") 
    b = tf.ones((n,), name="B") 
    with tf.device("/gpu:0"): 
     c = tf.add(a, b, name="C") 
    return c 

def run_and_summarize(target): 
    # turn off graph-rewriting optimizations 
    sess = tf.Session(config=tf.ConfigProto(graph_options=tf.GraphOptions(optimizer_options=tf.OptimizerOptions(opt_level=tf.OptimizerOptions.L0)))) 
    run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE) 
    run_metadata = tf.RunMetadata() 
    sess.run(target, options=run_options, run_metadata=run_metadata) 

    for device in run_metadata.step_stats.dev_stats: 
     device_name = device.device 
     if not (device_name.endswith("/cpu:0") or device_name.endswith("/gpu:0")): 
      continue 
     print(device.device) 
     for node in device.node_stats: 
      print(" ", node.node_name) 

現在你可以做到這一點

run_and_summarize(inputs_cpu()) 

與固定於CPU的投入運行,你會看到這個位置得到尊重

/job:localhost/replica:0/task:0/gpu:0 
    _SOURCE 
    C 
/job:localhost/replica:0/task:0/cpu:0 
    _SOURCE 
    A 
    B 

另一方面,當輸入未指定時

run_and_summarize(inputs_none()) 

你可以看到,現在所有的OPS放在GPU

/job:localhost/replica:0/task:0/cpu:0 
    _SOURCE 
/job:localhost/replica:0/task:0/gpu:0 
    _SOURCE 
    A 
    B 
    C 
+0

棒極了!我現在明白了。非常感謝! –

+0

BTW,最近[提交](https://github.com/tensorflow/tensorflow/commit/3f5f9585)澄清了評論中的行爲。基本上,如果你明確地設置設備,它將永遠在該設備 –

+0

我以前的印象是TF會隱式地分配ops給GPU,只要GPU和適合這些操作系統的內核可用。從這個描述我現在明白,如果其他與這些操作符具有輸入關係的操作符已經明確地(例如'with tf.device(「/ gpu:0」):'),則TF只會隱含地將操作分配給GPU。所以如果我沒有明確指定GPU的任何操作,TF也不會隱含地分配任何操作。那是對的嗎? – Drux

0
  1. 是。事實上,如果沒有內核可用於指定的設備,它將會失敗。但是有兩件事應該考慮:

    • 這可以用allow_soft_placement=True被重寫,如果會議的config
    • tf.device上下文管理器可以被嵌套,所以如果SimpleOp並不是這麼簡單,它也許已經包裹它的一些部件與with tf.device("/cpu:0"):
  2. 不,我知道的(意見,歡迎)。如果您使用* nix,python script.py | grep your_op_name,則可以隨時grep腳本輸出。缺點是你需要重新運行腳本兩次:第一次運行log_device_placement=Truegrep,第二次運行沒有它們。