Compilare Caffe2 e Detectron con supporto GPU su Windows (Parte 1 di 2)

giovedì 4 ottobre 2018

Nelle ultime settimane, ho avuto bisogno di provare ed usare alcuni modelli personalizzati implementati con il framework Caffe2 e Detectron. Sono progetti attivamente sviluppati su Linux, ma ho avuto bisogno di farli girare su Windows 10 con supporto GPU CUDA. E' possibile compilare Caffe2 per Windows, e una guida è disponibile, ma se c'è bisogno di usare Detectron (non supportato ufficialmente su Windows), è un po' più complicato, e sono necessarie alcune modifiche ai sorgenti e agli script di compilazione.

Dopo molti giorni di frustrante trial and error, compilazioni fallite, ricerca di idee e suggerimenti per risolvere vari problemi nelle discussioni GitHub e in vari articoli (grazie a Mianzhi Wang per questa guida), sono arrivato ad un modo aggiornato, pulito e riproducibile per compilare Caffe2 e Detectron su Windows, con supporto per CUDA 9 o CUDA 10.

Questo post, diviso in 2 parti, è una guida passo-passo per come l'ho fatto io, sperando che possa servire ad altri con le stesse necessità. Mettete in programma almeno 1 giorno di lavoro, per preparare il vostro sistema. Ci sono sicuramente modi migliori per gestire alcuni fix e modifiche, ma non ho avuto abbastanza tempo per approfondire. Se trovate miglioramenti, per favore fatemi sapere.

Qui, potete trovare la Parte 2, con tutti i passi neceserrai per compilare ed eseguire Detectron su Windows 10. Dovete seguire tutti i passi di questo post, prima di continuare con il prossimo.

ATTENZIONE: questa guida è stata scritta e provata nell'ultima settimana di settembre 2018. L'ho provata su 3 differenti macchine Windows di sviluppo (2 con CUDA 9.2, 1 con CUDA 10), con successo. Ma non posso assicurare al 100% che funzioni sulle vostre, e non posso neanche fornirvi supporto diretto in caso qualcosa non funzioni. Per favore, controllate attentamente le versioni dei pacchetti, le dipendenze, le commit git, ecc. E' molto probabile che versioni più recenti (di qualcunque pacchetto, dipendenza, codici sorgenti, strumenti) possano rompere la compilazione.


Passo 0: prerequisiti

Per compilare con successo Caffe2 e Detectron su Windows 10 con supporto GPU CUDA, i seguenti pre-requisiti sono obbligatori:

  • Windows 10: secondo la documentazione ufficiale, Windows 10 o successivo è richiesto per far girare Caffe2. Io ho usato Windows 10 Pro/Enterprise April 2018 Update (con tutti gli aggiornamenti, patch, fino al 30 settembre 2018).

  • Visual Studio 2017 (v15.8.4 o v15.8.5), con installati Visual C++, gli opportuni Windows SDK e gli strumenti di sviluppo per Python 3.6: compilare Caffe2 richiede un compilatore C++ compatibile. CUDA 8.0 supporta solo fino a Visual Studio 2015 con Update 3. Se usate Visual Studio 2017, dovete per forza fare una build con CUDA 9.x o CUDA 10.0. Io ho usato VS2017 Pro/Enterprise, ma la versione Community dovrebbe funzionare lo stesso.

  • CUDA 9.x/10.x con cuDNN 7.x installato: lo potete scaricare e installare dal sito nVidia Developers. Io ho provato la compilazione con CUDA 9.2.148 x64 + Patch1 + cuDNN 7.2.1.38 e CUDA 10.0.130 x64 + cuDNN 7.3.0.29. Siate estremamente attenti a non mischiare le versioni, e seguite le guide ufficiali per installarli. Controllate le variabili d'ambiente CUDA e verificate che puntino alla versione corretta che volete utilizzare per compilare. Inoltre, aggiornate i driver nVidia all'ultima versione disponibile e compatibile (come descritto nelle note di rilascio di CUDA). Io ho usato i driver nVidia GTX 1080 v411.63.

  • Python 2.7.x e VC++ Compiler Package: attualmente solo Python 2.7 è supportato (secondo alcuni commenti in GitHub Python 3 sarà supportato presto). Io ho installato Python 2.7.15 e Visual C++ Compiler Package for Python 2.7. Ho messo Python 2.7 in c:\Python27, senza aggiungerlo alla variabile d'ambiente PATH. Per alcuni comandi, per lanciare Python al di fuori di un virtual environment, se non viene trovato alla riga di comando, usate il path completo (es. c:\python27\python.exe).

  • Intel Math Kernel Library: per ottimizzare le operazioni su CPU, quando la GPU non è supportata. Io ho usato i binari v2018.3 x64 e il relativo package Python.

  • OpenCV 3.x: ho scaricato i binari pre-compilati per Windows x64 OpenCV 3.4.3. Li ho installati in c:\opencv.

  • CMake 3.12.x: richiesto per configurare e generare le soluzioni Visual Studio. Io ho usato CMake 3.12.2 x64.

  • Visual Studio Code, con le estensioni Python, per modificare i file di testo, script e codice Python. Ho usato VSCode v1.27.2.

  • git: per clonare i repository e le dipendenze. Ho usato git for Windows 2.19.0 e TortoiseGit 2.7.0.

Le macchine di sviluppo che ho usato per provare questa guida sono tutte equipaggiate con CPU Intel Core i7 7a gen, 256GB SSD, 16/32GB RAM, nVidia GTX 1070/1080.


Passo 1: Python Virtual Environment per Caffe2

  1. Aprite una x64 Native Tools Developer Command Prompt

  2. Clonate Caffe2 dal repository ufficiale su GitHub

    Al momento, Caffe2 e PyTorch sono in fase di unificazione, e il repo ufficiale ora è PyTorch.

    > mkdir c:\projects\pytorch
    > cd c:\projects\pytorch
    > git clone --recursive https://github.com/pytorch/pytorch.git
    

    Se preferite, potete anche clonare il repo usando TortoiseGit. Ricordatevi di attivare l'opzione recursive.

    Ho compilato con successo le seguenti versioni dal master branch:

    • 21ed7e51b606f9912b658ab63e016d7546f3b75c (2018-09-26 10:44:03)
    • 91b6458e2d0dba935da2cc7c2cdc6d7907bc3f48 (2018-09-18 10:11:55)
  3. Aggiorante pip all'ultima versione (io ho usato v18.0)

    > python -m pip install -U pip
    
  4. Installate virtualenv

    > python -m pip install virtualenv
    
  5. Create un nuovo virtual environment Python 2.7

    > python -m virtualenv caffe2env
    
  6. Attivate il virtual environment

    > caffe2env\Scripts\activate
    

    Per uscire dal virtual environment, potete usare:

    (caffe2env)> deactivate
    
  7. Installate i pacchetti richiesti (dalla guida ufficiale).

    Se volete usare numpy con ottimizzazioni Intel-MKL, potete prenderlo da qui e installarlo prima di qualunque altro pacchetto. Io ho usato la versione 1.15.2.

    (caffe2env)> pip install PATH_PER\numpy‑1.15.2+mkl‑cp27‑cp27m‑win_amd64.whl
    

    Altrimenti poteter usare il pacchetto standard:

    (caffe2env)> pip install numpy
    

    Quindi installate le altre dipendenze:

    (caffe2env)> pip install future
    (caffe2env)> pip install hypothesis
    (caffe2env)> pip install protobuf
    (caffe2env)> pip install six
    

    Un pacchetto richiesto non era specificato nella guida:

    (caffe2env)> pip install typing
    

    Ho usato Ninja per velocizzare le operazioni di compilazione, abilitando le build parallele per i componenti CUDA (non ancora supportato se si usa solo MSBuild), come descritto qui. Senza usare Ninja, la compilazione richiede quasi 4 ore. Con Ninja, meno di 1h.

    (caffe2env)> pip install ninja
    

    Il nostro ambiente è pronto per compilare.


Passo 2: configurare build_windows.bat

Per compilare Caffe2 in Windows, con tutte le opzioni richieste, bisogna modificare lo script fornito. Si trova in c:\projects\pytorch\scripts\build_windows.bat

Primo, bisogna impostare una serie di variabili d'ambiente (opzionalmente, possono essere impostate di volta in volta dalla riga di comando. Ho preferito metterle nello script per evitare di digitare i comandi ogni volta, all'apertura di una nuova console).

Prima di riga 29, aggiungete:

set CMAKE_GENERATOR=Ninja
set OpenCV_DIR=C:\opencv\build
set USE_CUDA=ON
set GEN_TO_SOURCE=1

Le variabili precedenti configurano Ninja come generatore (invece che Visual Studio 2017 x64), indicano dove trovare le librerie OpenCV e attivano il supporto per CUDA. L'ultima variabile serve per evitare un errore durante la compilazione, quando gli script di ATEN generano i corrispondenti file sorgenti.

Quindi cambiate alcuni parametri per cmake.

  • Alla riga 71, impostate la versione corretta dell'architettura CUDA da supportare. Nel mio caso, volevo far girare CUDA 9/CUDA 10 su GTX 1070/1080 così, secondo questo post, ho dovuto usare l'architettura 6.1 (lasicando 5.0 non funzionava). Per favore, cambiate questo parametro a seconda della vostra combinazione GPU/CUDA.

    -DTORCH_CUDA_ARCH_LIST=6.1
    
  • Alla riga 80, abilitate OpenCV:

    -DUSE_OPENCV=ON
    
  • Alla riga 82, abilitate i binding Python:

    -DBUILD_PYTHON=ON
    
  • Alla riga 86, siccome stiamo usando Ninja, rimuoviamo l'opzione non supportata:

    -- /maxcpucount:%NUMBER_OF_PROCESSORS%
    

Passo 3: qualche modifica qua e là

Per compilare con successo, bisogna apportare anche alcuni cambiamenti ai sorgenti (è possibile che release future avranno già tali modifiche, oppure che si renderanno necessarie modifiche differenti), e alcuni file sono da copiare in varie posizioni, per renderli disponibili durante le operazioni di compilazione e link.

  1. Create la cartella build\caffe2 in c:\projects\pytorch
  2. Create la cartella libs in c:\projects\pytorch\caffe2env
  3. Copiate c:\python27\libs\python27.lib nelle due cartelle appena create:
    • c:\projects\pytorch\build\caffe2
    • c:\projects\pytorch\caffe2env\libs
  4. Rimuovete tutti gli AT_CPP14_CONSTEXPR da c:\projects\pytorch\aten\src\ATen\core\ArrayRef.h, per sistemare un problema con il compilatore VC++ 17.
  5. Sostituite un paio di "or" con "||" in c:\projects\pytorch\caffe2\image\image_input_op.h, per risolvere un problema di compilazione.

Nella compilazione per Windows, operatori aggiuntivi e personalizzati non possono essere caricati dinamicamente (un bug? Date un'occhiata alle discussioni in GitHub qui, e qui). Una possibile soluzione è quella di muovere Detectron tra gli operatori built-in di Caffe2.

  1. Copiate o spostate modules\detectron in caffe2\operators\detectron
  2. Rimuovete la sotto-cartella "detectron" da modules\CMakeLists.txt (commentate completamente il check condizionale su MSVC e BUILD_SHARED_LIBS).
  3. Cambiate caffe2\operators\detectron\CMakeLists.txt in maniera simile a caffe2\operators\RNN\CMakeLists.txt:
    file(GLOB Detectron_CPU_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
    file(GLOB Detectron_GPU_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cu)
    
    set(Caffe2_CPU_SRCS ${Caffe2_CPU_SRCS} ${Detectron_CPU_SRCS} PARENT_SCOPE)
    set(Caffe2_GPU_SRCS ${Caffe2_GPU_SRCS} ${Detectron_GPU_SRCS} PARENT_SCOPE)
    
  4. In caffe2\CMakeLists.txt aggiungete la sotto-cartella "detectron" (riga 91):
    add_subdirectory(operators/detectron)  
    
  5. Sistemate un problema con i sorgenti Eigen CUDA, c:\projects\pytorch\third_party\eigen\Eigen\src\Core\arch\CUDA\Half.h. Guardate qui che cosa cambiare.

Passo 4: compilazione

Ora, tutto dovrebbe essere pronto per compilare con successo Caffe2.

  1. Aprite una x64 Native Tools Developer Command Prompt
  2. Attivate il virtual environment
    > cd c:\projects\pytorch
    > caffe2env\Scripts\activate
    
  3. Eseguite lo script di compilazione
    > scripts\build_windows.bat
    

La compilazione avrà inizio e richiederà un po' di tempo (circa 40/45 minuti sulle mie macchine, usando Ninja; dalle 4 alle 5 ore senza). Ci saranno moltissimi messaggi di warning... potete ignorarli, e non ci dovrebbe essere nessun messaggio di errore. Quando il processo di build è terminato, avrete la vostra build di Caffe2 con supporto per GPU CUDA per Windows 10 pronto nella cartella c:\projects\pytorch\build\caffe2.

Prima di poterla usare, io ho dovuto copiare a mano alcune DLL mancanti per Intel MKL e OpenCV.

  • Da C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2018.3.210\windows\redist\intel64_win\compiler copiate

    • libiomp5md.dll
    • libiomp5md.pdb
    • libiompstubs5md.dll

    in c:\projects\pytorch\build\caffe2\python

  • Da C:\opencv\build\x64\vc15\bin copiate

    • opencv_world343.dll

    in c:\projects\pytorch\build\caffe2\python

Passo 5: test

Per verificare che la build con supporto CUDA è funzionante, potete provare con questo comando:

> python -c "from caffe2.python import workspace; print(workspace.NumCudaDevices())"

Dovrebbe stampare un numero > 0. Se no, o se c'è qualche altro errore, la vostra build di Caffe2 ha qualche problema (es. configurazione sbagliata, dipendenze mancanti, DLL mancanti, dispositivo CUDA non supportato, ecc.). Controllate su Internet, su StackOverflow, nelle issues dei repo GitHub per idee e suggerimenti su come risolverli.


Questo è tutto per adesso. Una guida piuttosto lunga, ma ci dovrebbe essere tutto per riuscire a compilare Caffe2 con tutti i componenti richiesti per far funzionare Detectron. Nel prossimo post, vi spiegherò come farlo su Windows. A presto!