1. 程式人生 > >記困擾很久的pytorch載入模型OOM,python import執行流程,python“懶執行”,whindows控制ubuntu遠端桌面

記困擾很久的pytorch載入模型OOM,python import執行流程,python“懶執行”,whindows控制ubuntu遠端桌面

前言

半路接手專案,閱讀程式碼,解決bug,優化速度。

part one

  1. 1050 Ti載入模型時OOM model.load_state_dict(torch.load(path))

Copies parameters and buffers from :attr:state_dict into this module and its descendants. If :attr:strict is True, then the keys of :attr:state_dict must exactly match the keys returned by this module’s :meth:~torch.nn.Module.state_dict

function. Arguments: state_dict (dict): a dict containing parameters and persistent buffers. strict (bool, optional): whether to strictly enforce that the keys in :attr:state_dict match the keys returned by this module’s :meth:~torch.nn.Module.state_dict function. Default: True

  1. 繼續debug,發現在某個py指令碼中,有變數賦值 sess, saver, net = load_tf_model()
    所以在import的時候,這句程式碼會被解釋執行,load_tf_model()函式中, net = get_network("VGGnet_test")執行了模型載入操作,這裡耗掉3253MB。 注意到tensorflow建立了2個gpu task,第一個耗掉3253MB: Creating TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 3253 MB memory) 然後第二個Task: Creating TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 29 MB memory)

以上都發生在import模組時。

關於Python import

以前光是知道Python解釋執行,一行行解釋執行;Java編譯執行,編譯完到處執行。 但是沒注意到Python import匯入模組執行流程: 在python中使用import語句匯入模組時,python通過三個步驟來完成這個行為。 1:在python模組載入路徑中查詢相應的模組檔案 2:將模組檔案編譯成中間程式碼 3:執行模組檔案中的程式碼

在python中模組的匯入動作只發生一次。也就是說當一個模組在一個檔案中被匯入過一次以後,當另外的檔案繼續需要匯入這個模組時,python首先會在sys.modules這個變數中查出是否已經匯入過這個模組,如果已經匯入過則上面三個步驟不會執行,直接引用之前匯入的記憶體中的內容。 在步驟2中,python首先會查詢對應模組的.pyc檔案,看該檔案的最後修改時間是否比對應的.py檔案的走後修改時間早,如果遭遇.py檔案的最後修改時間,則重新編譯模組並重新生成位元組碼檔案。注意,一個python程式的頂層檔案不會生成.pyc檔案。 當python完成步驟2以後會執行python檔案中的語句,以生成對應的物件屬性,比如def語句生成該模組的一個函式屬性等。因為這個特性,假如模組中有一個print語句 , 那麼, 當該模組被第一次載入的時候,該輸出語句就會將內容輸出,但是由於模組只能被import一次,所以,當模組第二次被載入的時候,上面這三個步驟都不會被執行,那麼,這個輸出不會再次出現。 CSDN: tuxl_c_s_d_n_python import匯入模組執行流程分析

舉個例子:a.py

a = 3
print(3)

b.py:

import a

也就是說,b除了匯入a,什麼都不做。但是執行 b.py,是會打印出3的。 再舉個例子: 將a.py改為:

a = 3

def c():
    print(a)

而b指令碼不變,執行,不會列印。 所以,平常寫python程式碼時,如果想提升速度或者節約記憶體,能在方法裡賦值的變數儘量少寫在全域性, 關查那些官方程式碼,你也會發現這個問題。

以上內容,讓熟悉python的人見笑了,哈哈。Java是不會這樣的,因為就一個main函式,除非併發程式設計或者static啥的,不會出現這樣的“提前”計算的情況。這樣一想,spar等一些框架的laze 操作,真的不錯。

part two

import結束,進入main執行程式碼時: rois = sess.run([net.get_output('rois')[0]], feed_dict=feed_dict) 再次分配GPU, ran out of memory trying to allocate 3.39GiB. The caller indicates that this is not a failure, but...

疑問: gpu不夠分配,是不是自動全部轉入cpu計算? 應該是的,我安裝的是gpu版本的框架,當不強制設定使用GPU時,只是warning視訊記憶體不夠分配,提示幾次後,程式碼正常執行,但是強制設定為gpu執行時,程式碼報錯。所以我猜測:gpu不夠分配,是不是自動全部轉入cpu計算。

part three

上面的幾次GPU 資訊,應該是分配GPU,並沒有使用吧? 先放著了,借朋友1080 Ti用一用。 關於cuda 、cudnn、tensorflow的版本匹配:

TensorFlow 1.7 may be the last time we support Cuda versions below 8.0. Starting with TensorFlow 1.8 release, 8.0 will be the minimum supported version. TensorFlow 1.7 may be the last time we support cuDNN versions below 6.0. Starting with TensorFlow 1.8 release, 6.0 will be the minimum supported version.

但是1.6.0以及1.5.0的釋出:

Prebuilt binaries are now built against CUDA 9.0 and cuDNN 7. Prebuilt binaries will use AVX instructions. This may break TF on older CPUs.

保險起見,還是tensorflow-gpu==1.4.1。2017年12月9日釋出的。 注意:1.4.1沒有Windows的二進位制檔案。1.4.1只是修復了CloudML Engine,CloudML Engine僅支援Linux,Windows不受影響。

報錯

  1. 提示缺少庫:ImportError: libcublas.so 檢查你的配置檔案~/.bashrc中配置的cuda的lib是否正確,也就是說,你安裝cuda時,是不是改了檔名。
  2. command not found: shopt 如果你在用zsh:(其實個人感覺,fish更好用) 將所需配置修改寫入~/.zshrc 執行 source ~/.zshrc

whindows控制ubuntu遠端桌面