CMake Cuda e Python

Peri

Nuovo Utente
82
3
Ciao
Da ore (molte ore) sto impazzendo appresso il mio CMake
Vi metto qui quello che ho scritto fino ad ora, ve lo descrivo e vi dico le mie problematiche:
L'obiettivo è creare una libreria chiamabile da python, essa usa lo standard di C11 tuttavia per certe esigenze ho dovuto inserire Python.h, l'estensione CUDA e presto anche OpenMP per aumentare la potenza di calcolo (nonostante siano funzioni C sono estremamente dispendiose). Questo è il mio CMake.
C:
cmake_minimum_required(VERSION 3.22)
if(POLICY CMP0126)
    cmake_policy(SET CMP0126 NEW)
endif()
if(POLICY CMP0102)
    cmake_policy(SET CMP0102 NEW)
endif()

# compilers
set(CMAKE_CUDA_COMPILER "/usr/local/cuda-12.3/bin/nvcc")

project(MasterSoftwareProject CUDA C)

# external contents
find_package(PythonLibs REQUIRED)
find_package(OpenMP REQUIRED)
find_package(CUDA REQUIRED)

# set source files
set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(SRC_PCH
    ${SRC_DIR}/darr.c
    ${SRC_DIR}/c_dist.c
    ${SRC_DIR}/c_digital.c
    ${SRC_DIR}/c_synth.c
    ${SRC_DIR}/pool_runner.c
    ${SRC_DIR}/sort.c
    ${SRC_DIR}/read_input_file.c
    ${SRC_DIR}/io_synth_file.c
    ${SRC_DIR}/pool.c
)
set(SRC_CUDA
    ${SRC_DIR}/fuzzy_KMeans.cu
)
set(SRC_MSP
    ${SRC_DIR}/MSP.c
)

# make local libraries
add_library(lib_pch OBJECT ${SRC_PCH})
add_library(lib_cuda OBJECT ${SRC_CUDA})
add_library(lib_msp OBJECT ${SRC_MSP})
set_property(TARGET lib_pch PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET lib_cuda PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET lib_msp PROPERTY POSITION_INDEPENDENT_CODE ON)
add_dependencies(lib_cuda lib_pch)
add_dependencies(lib_msp lib_cuda lib_pch)

# make MSP library
include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/inc
    ${CUDA_INCLUDE_DIRS}
    ${CUDA_TOOLKIT_ROOT_DIR}
    ${PYTHON_INCLUDE_DIRS}
)
link_libraries(
    ${CUDA_LIBRARIES}
    ${CUDA_cublas_LIBRARY}
    ${PYTHON_LIBRARIES}
)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.venv/lib64/python3.10/site-packages)

add_library(MSP SHARED
    $<TARGET_OBJECTS:lib_msp>
    $<TARGET_OBJECTS:lib_cuda>
    $<TARGET_OBJECTS:lib_pch>
)

Ho un progetto con numerosi file ma che alla fin fine sono facilmente distinguibili:
in MSP.c troviamo scritto
C:
#include <Python.h>
e in esso definisco in modo opportuno il collegamento a python di 3 funzioni: digital, distance, synthesis
facendo quindi
Python:
from libMSP import distance, digital, synthesis
ottengo le mie 3 funzioni. E fino a qua ok.
Ora queste funzioni attingono a numerosi file .h e file .c e sono un po' tutti indipendenti.
Ora...
Una funzione dovrà usare la GPU, quindi ho scaricato CUDA dal sito ufficiale e ho scritto un minimo di codice per testarla nel mio progetto.
Ecco non ci sto riuscendo...
Il problema è che MSP.c richiede le definizioni in fuzzy_KMeans.cu per avere la libreria finale tutta carina e utilizzabile
Ma fuzzy_KMeans.cu deve essere compilato con un altro compilatore, ossia nvcc!
fuzzy_KMeans.cu richiede le definizioni in darr.c (come anche MSP.c le richiedeva già di base, prima di mettere in mezzo CUDA).
Quindi che ho fatto:
ho compilato darr.c
ho compilato fuzzy_KMeans.cu con dipendenza da darr.c
ho compilato MSP.c con dipendenza da entrambi
metto tutto insieme in un'unica libreria e via!
Tutta la compilazione sembra filare liscio, ma poi quando vado su python mi dice:
Codice:
Traceback (most recent call last):
  File "/.../software.py", line 140, in <module>
    from libMSP import digital, distance, synthesis
ImportError: /.../software/.venv/lib/python3.10/site-packages/libMSP.so: undefined symbol: _Z10darr_allocl
darr_alloc è una funzione dichiarata in darr.h (correttamente richiamata da tutti i file, almeno in C ne sono convinto) e definita in darr.c

Da spiegare è una cosa stupidissima ma da ore ci sto sopra e credo proprio di essermi bloccato...
Grazie mille in anticipo
 

Peri

Nuovo Utente
82
3
Ok, ho trovato un sistema e funziona.
Probabilmente è una soluzione del piffero ma ho appreso molte cose scoprendola quindi vi condivido la soluzione.
In pratica ho notato che quando nel cmake scrivo:
Python:
add_library(MSP SHARED
    #proprio elenco di file sorgente
)
Lui mette in automatico il compilatore più adatto e fino a qua ok.
Ma non sapevo che quando la compilazione richiede un mix di c e cuda allora compila con g++ (un terzo compilatore del tutto inatteso) quindi cosa fa?
  1. con il compilatore nvcc compila i file per cuda, ottenendo i rispettivi oggetti
  2. con cc compila i file scritti interamente in c, ottenendo i rispettivi oggetti
  3. con g++ compila i file scritti in c che richiedono gli oggetti compilati con nvcc
E quindi niente questo cambia tutto perché un compilatore g++ non è bene che legga codice scritto c senza essere debitamente avvisato (specie se in questo codice c'è la porzione utile per condividere la libreria con python)
Inoltre ho scoperto che nvcc lo devo pensare come un compilatore g++ quando legge codice c.
In particolare essendo il mio codice scritto interamente in C (eccetto dove lavoro con CUDA) ho scritto all'inizio di ogni sorgente:
C:
/* apro un contesto in cui il compilatore sa che deve leggere il codice come fosse C */
#if defined(__cplusplus) || defined(__NVCC__)
    extern "C"{
#endif

/* altro codice del file sorgente, eventuali chiamate a file header scritti interamente in C */
/* ... */

/* chiusura del contesto extern "C" */
#if defined(__cplusplus) || defined(__NVCC__)
    }
#endif
Così facendo tutto ha funzionato e siamo andati a casa sereni 😁
 
  • Mi piace
Reazioni: BAT

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!