1. 程式人生 > >Caffe Python介面多程序提取特徵

Caffe Python介面多程序提取特徵

原文地址:http://yongyuan.name/blog/caffe-python-extract-feature-parallel.html

https://thief.one/2016/11/24/Multiprocessing-Pool/

https://jingsam.github.io/2015/12/31/multiprocessing.html

想象這樣一個場景:伺服器上配備了很多GPU顯示卡,而你又使用的是Caffe,不幸的是,你還選用了Python來寫程式碼,不幸中的不幸是你還要在短時間內處理百萬千萬規模的圖片。那麼,問題來了,Caffe本身對多卡的支援就不是很好,而你還要用Python,而且即便你通過設定batch size的大小來加快處理速度,但你還是隻把一張顯示卡用起來。有沒有辦法把所有的GPU都用起來,並行提取特徵呢?

上面這個問題在實際中是一個經常會碰到並且繞不過的問題,小白菜在近期也遇到了此問題,並且上面那些設定的條件小白菜不幸都一一躺槍。雖然如此,問題還是要解決的。下面小白菜聊聊如何使用python 的multiprocessing多程序並行庫來把伺服器上的多張GPU都用起來,進行特徵的並行提取。在正式給出具體的解決方案之前,還是有必要了解multiprocessing多程序並行庫的。

multiprocessing多程序並行庫

multiprocessing對於程序的管理,是使用程序池pool進行管理的。pool允許使用者指定程序數目,線上程池未滿的時候,如果新的請求提交過來,則pool會建立新的程序來執行該請求,如果池中的程序數已經達到規定最大值,那麼該請求就會等待,直到池中有程序結束,才會建立新的程序來執行它。pool對於程序的管理,有兩種方式,分別是非同步方式(也稱非阻塞方式)和同步方式(也稱阻塞方式),對應的方法為apply_async()和apply()。

  • apply(): 同步方式(也稱阻塞方式)。阻塞,顧名思義,在執行該任務的時候,把所有的介面資源都堵住了,其他的任務必須等待這個任務執行完後,再釋放資源後,才能執行其他的任務,所以非常的好理解。
  • pool.apply_async(): 非同步方式(也稱非阻塞方式)。有了上面阻塞的解讀,小白菜以為非同步方式已經非常直白了。

程序池管理pool還有一些其他的方法,這裡不再做詳細的展開了,更多關於Python的multiprocessing的解讀,可以參考Multiprocessing.Pool正確使用 Multiprocessing 的姿勢,寫得直白易懂。

有了上面對Python的multiprocessing的認識,我們再回到使用python的multiprocessing多程序並行庫來把伺服器上的多張GPU都用起來這個問題上。根據對pool對程序池管理的方法,顯然pool.apply_async()

是我們需要的,確定好了這個後,小白菜再簡單聊聊並行化設計的思路。

並行化方案

問題定義:假設需要處理的圖片有800萬,伺服器上有8塊GPU,如何使用python 的multiprocessing多程序並行庫來把伺服器上的多張GPU都用起來,進行特徵的並行提取。

對於上述給出的問題定義,小白菜設計的並行化方案為:將800萬分成8等分,啟動8個程序,每個程序使用一塊GPU,並且每一個程序載入一份預訓練的模型,這樣就可以把8塊GPU都用起來了。此種方案,可以最大限度的使用GPU,有多少塊GPU,就可以用多少GPU,下面是具體的編碼。

具體編碼

有了上面對multiprocessing和並行化方案後,在具體編碼的時候,要做的事情其實非常簡單,主要需要完成的就是兩件事:

  • 把圖片資料按GPU的數目進行等量劃分,即寫一個split_list()函式
  • 正常編寫特徵提取程式碼,寫一個gpu_task函式

具體程式碼如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: [email protected]


import multiprocessing
from multiprocessing import Process, freeze_support, Pool
import sys
import os
import caffe
import numpy as np
import scipy
import h5py


def split_list(alist, wanted_parts=1):
    length = len(alist)
    return [ alist[i*length // wanted_parts: (i+1)*length // wanted_parts] 
             for i in range(wanted_parts) ]

def gpu_task(prototxt, caffemodel, layer, path_images, out, gpu=0):
    num_images = len(path_images)

    h5f = h5py.File(out, 'w')

    # set gpu card
    caffe.set_device(gpu)
    caffe.set_mode_gpu()

    # init NN
    net = caffe.Net(prototxt, caffemodel, caffe.TEST)
    net.forward()

    features = []
    image_names = []

    for i, path in enumerate(path_images):
        print "%d(%d), %s"%((i+1), num_images, os.path.basename(path))
        if os.path.splitext(os.path.basename(path))[0][-6:] != 'single':
            img = ...
 
            # extract feature

            feat = ...
 
            features.append(feat)
            image_names.append(os.path.basename(path))      

    features = np.array(features)
    h5f['feats'] = features
    h5f['names'] = image_names
    h5f.close()    
    print "gpu %d task has finished..." % (gpu)

if __name__ == '__main__':

    multiprocessing.freeze_support()
    pool = multiprocessing.Pool()
    
    dir_images = '....'
    path_images = [os.path.join(dir_images, f) for f in sorted(os.listdir(dir_images)) if f.endswith('.jpg')]
    layer = '...'
    prototxt = 'VGG_ILSVRC_16.prototxt'
    caffemodel = 'VGG_ILSVRC_16_layers.caffemodel'
    out = '...'

    parts = 8 # 8個程序

    out_files = []
    for i in xrange(parts):
        out_files.append(os.path.join(out, str(i) + '.h5'))

    blocks = split_list(path_images, wanted_parts = parts)
  
    for i in xrange(0, parts):
        pool.apply_async(gpu_task, args = (prototxt, caffemodel, layer, blocks[i], out_files[i], i + (8 - parts),))
    
    pool.close()
    pool.join()

上面那些...的部分,是小白菜刻意省略的,具體在實際使用的時候,可以結合自己的需要來做更改。另外一個pool.close()pool.join()的次序一定不能反,否則會出錯。執行完close後不會有新的程序加入到pool,join函式等待所有子程序結束。

對於特徵的儲存,可以採用hdf5的格式進行儲存,上面每一個程序提取的特徵,儲存在一個h5(HDF5格式)檔案中,這樣對於八個程序,可以得到8份小檔案,每一份檔案裡存了影象檔名及其對應的特徵。


相關推薦

Caffe Python介面程序提取特徵

原文地址:http://yongyuan.name/blog/caffe-python-extract-feature-parallel.html https://thief.one/2016/11/24/Multiprocessing-Pool/ https://jing

Python學習程序併發寫入同一檔案

最近學習了Python的多程序,想到我的高德API爬蟲那個爬取讀寫速度我就心累,實在是慢,看到多程序可以充分利用CPU核數我就開始完善我的程式碼,不過過程是艱辛的,在此之中出現了很多問題,其中最大的問題是爬取的資料是正確的,但是讀寫到Excel中卻開啟是空,想了半天也沒解決,腦子笨沒辦法,不過我

python mutilprocessing程序程式設計

  `為了更好的理解本文內容,請務必先了解Synchronization、Asynchronization、Concurrent、Mutex等基本概念    multiprocessing是一個類似於Threading模組的由API產生程序的包,關於Threading模組可以參

python程序模組multiprocessing

程序: python裡程序是multiprocessing模組 用法和多執行緒沒有什麼區別(os.getpid()是獲得程序號,ppid是父程序號) import time ,os import multiprocessing def f(name): time.sleep(

程序與執行緒(2)- python實現程序

python 實現多程序  參考連結: https://morvanzhou.github.io/tutorials/python-basic/multiprocessing/ python中實現多程序的模組:multiprocessing 注意:在windows系統下

python程序應用--讀取儲存圖片

例一 使用Pool.map函式實現多程序,稍微有點low,可用範圍較窄。 #coding=utf-8 from multiprocessing import Pool import scipy from scipy import misc import os impor

python使用程序

python多執行緒適合IO密集型場景,而在CPU密集型場景,並不能充分利用多核CPU,而協程本質基於執行緒,同樣不能充分發揮多核的優勢。 針對計算密集型場景需要使用多程序,python的multiprocessing與threading模組非常相似,支援用程序池的方式批量建立子程序。 建立單個Proce

Python程序 multiprocessing.Pool 類

multiprocessing包是Python中的多程序管理包。它與 threading.Thread類似,可以利用multiprocessing.Process物件來建立一個程序。該程序可以允許放在Python程式內部編寫的函式中。該Process物件與Thread物件的用

Python multiprocessing 程序程序間傳遞Lock 遇到的問題

無法傳遞 Lock物件 from multiprocessing import Pool,Lock def text(i,lock): print(i) lock.acquire() DOSOMETHING lock.release() if __na

執行緒與程序Python實現【Python實現程序

上一篇部落格介紹了多執行緒與多程序的理論部分,這篇部落格將參考部落格以及各種教程完成Python多程序實現部分。 multiprocessing模組 Process 類 multiprocessing.Process(group=None, target=N

Caffe Python 介面 API

Caffe 有 Python 和 Matlab 介面,都可以用於直接呼叫底層的 Caffe 函式(C++ 實現)。而且 Python 介面可以用於編寫指令碼,生成自定義的 prototxt 檔案,即網路結構定義檔案。 一些大型網路比較深,而且結構複雜,比如 Re

keras tensorflow 在python程序執行

from multiprocessing import Process import os def training_function(...): import keras # 此處需要在子程序中 ... if __name__ == '__mai

Caffe-Python介面常用API參考

1、io.py原始碼解讀 主要是定義了一個transformer,preprocess和deprocess操作,完成caffe和python之間資料的格式轉換等, 注意caffe: BGR,0-255,C*H*W,而python是RGB, 0-1,H*W*C的資料格式,所以

python程序(multiprocessing)

python中多程序(multiprocessing) 一、multiprocessing中使用子程序概念 from multiprocessing import Process 可以通過Process來構造一個子程序 p = Process(target=fun,args=(arg

ubuntu14.04安裝caffe+python介面

1 ubuntu系統安裝 2 caffe環境安裝 General dependencies sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobu

python爬蟲——程序multiprocessing

其實多程序相對來說不是特別適合用來做爬蟲,因為多程序比較適用於計算密集型,而爬蟲是IO密集型,因此多程序爬蟲對速度的提升不是特別明顯,但是將爬蟲改為多程序比較簡單,只需簡單的幾行程式碼即可搞定,所以在修改我的爬蟲提升效率時,我最先實現的是多程序爬蟲。(然而速度真

Python程序的使用 Python執行緒(threading)與程序(multiprocessing )示例程式碼 Python程序程式設計

程序:程式的一次執行(程式載入記憶體,系統分配資源執行)。每個程序有自己的記憶體空間,資料棧等,程序之間可以進行通訊,但是不能共享資訊。 執行緒:所有的執行緒執行在同一個程序中,共享相同的執行環境。每個獨立的執行緒有一個程式入口,順序執行序列和程式的出口。 執行緒的執行可以被強佔,中斷或者暫時被

python爬蟲入門八:多程序/執行緒 python佇列Queue Python多執行緒(2)——執行緒同步機制 python學習筆記——多程序中共享記憶體Value & Array python多程序 Python多程序 Python 使用multiprocessing 特別耗記

什麼是多執行緒/多程序 引用蟲師的解釋: 計算機程式只不過是磁碟中可執行的,二進位制(或其它型別)的資料。它們只有在被讀取到記憶體中,被作業系統呼叫的時候才開始它們的生命期。 程序(有時被稱為重量級程序)是程式的一次執行。每個程序都有自己的地址空間,記憶體,資料棧以及其它記錄其執行軌跡的輔助資料

caffe python介面訓練VGG

# -*- coding: utf-8 -*- """ @author: root """ #matplotlib是python最著名的繪相簿 import matplotlib.pyplot as plt import caffe #import cv2 from num

python-->程序

pythn 多程序 python中的多執行緒無法利用多核優勢,若想要充分地使用多核CPU的資源(os.cpu_count()檢視),在python中大部分情況需要使用多程序。Python提供了multiprocessing模組用來開啟子程序,並在子程序中執行我們定製的任務(比如函式),該模組與多執行緒模組t