Konsistensi penunjuk fungsi Cuda [duplikat]

Saya baru-baru ini mencoba menggunakan penunjuk fungsi untuk secara dinamis menentukan beberapa tahap pemrosesan dalam aplikasi saya, yang berjalan pada sm_30.

Akan sulit untuk memposting kode di sini, karena ada banyak file dan fungsi berbeda yang terlibat, tetapi pada dasarnya, saya memulai dari contoh yang disertakan dalam Cuda Toolkit 5.0.

Saya mengalokasikan buffer fungsi perangkat tempat saya menyalin penunjuk fungsi perangkat, yang didefinisikan seperti dalam sampel berkat cudaMemcpyfromsymbolAsync yang digunakan dengan Jenis salinan DeviceToDevice.

Penunjuk perangkat saya didefinisikan seperti ini di .cu.h :

//device function pointer model
typedef void (*func)(structGpuArgument*);

//Declaring a function
__device__ void gpuFunc1(structGpuArgument* arg1);

di tempat lain saya punya .cu yang menyertakan deklarasi sebelumnya yang berisi kode berikut:

//get the actual function pointer
__device__ func gpuFuncPtr = gpuFunc1;

//Buffer to store a list of function pointer
func* pFuncDevBuffer;
cudaMalloc(&pFuncDevBuffer,NB_FUNC*sizeof(func));

//copy the actual function pointer (symbol) to the list buffer 
cudaMemcpyFromSymbolAsync( pFuncDevBuffer+i ,gpuFuncPtr,sizeof(func),0,cudaMemcpyDeviceToDevice,stream)

//Launch the kernel that will use the functions
kernel_test<<<1,10,0,stream>>>(pFuncDevBuffer)
...

//defining the kernel that uses pointer buffer
__global__ void kernel_test(func* pFuncDevBuffer)
{
   printf("func address : %p\n",pFuncDevBuffer[0]);
   pFuncDevBuffer[0](NULL);
}

//defining the function pointed by the function pointer
__device__ void gpuFunc1(structGpuArgument* arg1)
{
     do_something;
}

Faktanya, semuanya berfungsi dengan baik selama kernel global yang menggunakan buffer fungsi perangkat dalam argumen didefinisikan dalam file yang sama dengan fungsi dan penunjuknya. Kernel kemudian dapat mencetak alamat fungsi (0x4) dan menjalankan kodenya tanpa masalah. Saya tidak menggunakan kompilasi terpisah.

Ketika, dalam contoh program yang sama, kernel kedua, yang didefinisikan di tempat lain, menggunakan buffer penunjuk fungsi yang sama dalam argumen, ia dapat mencetak alamat memori yang sama untuk penunjuk fungsi (0x4) tetapi jika ia mencoba menjalankannya, itu akan terjadi. gagal mengeluarkan Instruksi ilegal pada 0x00000000 di cuda-memcheck. Panggilan API cuda lainnya terhenti setelahnya, saya perlu me-reboot komputer saya (reset melalui cuda-smi tidak didukung di GPU saya).

Saya ingin tahu apakah ada masalah umum dalam menggunakan penunjuk fungsi dengan cara ini, yaitu dengan menggunakan buffer penunjuk fungsi yang ditentukan dalam file lain, tetapi berbagi definisi penunjuk fungsi yang sama.

Juga jika ada latihan untuk menyetel ulang perangkat setelah segfault tanpa me-reboot seluruh sistem, ini dapat membantu saya menghemat waktu saat men-debug aplikasi saya.

Terima kasih untuk bantuannya


person Tobbey    schedule 07.05.2013    source sumber
comment
Anda menautkan kode perangkat dalam 2 file terpisah secara bersamaan. Anda perlu menggunakan penaut perangkat   -  person Robert Crovella    schedule 07.05.2013
comment
@RobertCrovella Terima kasih atas jawaban Anda, tapi bisakah Anda lebih spesifik? Karena saya tidak memiliki kesalahan penautan untuk saat ini, dan saya menggunakan CUDA.Cmake untuk membangun proyek saya, yang menyembunyikan saya sebagai bagian dari proses kompilasi/penautan. Sejauh yang saya tahu, tidak ada memori yang dibatasi proses di GPU nvidia, jadi mengapa kernel saya tidak dapat mengakses dan memuat kode dari alamat yang dibacanya dari buffer (0x4)?   -  person Tobbey    schedule 07.05.2013
comment
Setelah masalah direproduksi dengan contoh sederhana, tampaknya Anda benar. Di nsight, saya membuat versi gagal yang dikompilasi dalam mode seluruh program dan versi berhasil tanpa mengkode ulang apa pun kecuali mengatur opsi kompilasi terpisah. Masalah saya sekarang adalah pertama-tama saya tidak memahami dokumentasi nvcc, apa sebenarnya singkatan dari kode perangkat yang dapat direlokasi dan kompilasi yang dapat dipisahkan, dan apa hubungannya dengan masalah saya. Di sisi lain, ketika mencoba menggunakan kompilasi terpisah dan kode perangkat yang dapat direlokasi di cuda.cmake saya mendapatkan banyak kesalahan tautan referensi yang tidak terdefinisi.   -  person Tobbey    schedule 07.05.2013
comment
Maaf aku sedang berada di pesawat. Sepertinya Anda berada di jalur yang tepat untuk mencari tahu. Jika Anda memiliki kode perangkat dalam 2 file yang perlu memanggil atau mereferensikan satu sama lain, Anda perlu menggunakan linker perangkat (yang digunakan saat Anda memilih kompilasi terpisah). Anda mungkin ingin membaca bagian manual nvcc tersebut di docs.nvidia.com Maaf saya tidak dapat membantu dengan cmake.   -  person Robert Crovella    schedule 07.05.2013