#c #c #cuda #nsight
#c #c #cuda #взгляд
Вопрос:
Это первый раз, когда я пытаюсь создать свое приложение CUDA в NSight Ubuntu, чтобы извлечь выгоду из оптимизации и профилирования. Это приложение отлично работает с терминала, используя nvcc
(makefile) в Ubuntu 20 (или 18, 16). У меня есть несколько файлов .cu, .c и .h. Все файлы сначала включаются в файл flags.h. Мой код начинается с main.cu (имеет main()
функцию), и в этом файле есть # include «flags.h», чтобы убедиться, что все файлы включены для компиляции кода. флаги.у h также есть много #define
, которые позже будут использоваться в разных файлах .cu и .c.
Однако внутри NSight ни один из параметров #define, определенных во flags.h, не распознается ни в одном из файлов, и я получаю сообщение об ошибке. Ниже приведен скриншот ошибки. Я прилагаю простую задачу square_array, разделенную на 3 файла(main.cu , флаги.h и square_.cu ).
Я не могу построить это в NSight. Может кто-нибудь попробовать его построить и дайте мне знать, пожалуйста. Любая помощь или предложение будут высоко оценены.
main.cu
#include <stdio.h>
#include <stdlib.h>
#include "flags.h"
int main(void) {
int i;
int *a_h, *a_d;
CUDA_CHECK_RETURN(cudaMalloc((void**) amp;a_d, sizeof(int) * WORK_SIZE));
a_h = (int *)malloc(sizeof(int) * WORK_SIZE); // Allocate array on host
for (i = 0; i < WORK_SIZE; i )
a_h[i] = i 2.;
int block_size = 4;
int n_blocks = WORK_SIZE/block_size (WORK_SIZE%block_size == 0 ? 0:1);
sq_array<<<n_blocks, block_size>>>(a_d);
CUDA_CHECK_RETURN(cudaGetLastError());
CUDA_CHECK_RETURN(cudaMemcpy(a_h, a_d, sizeof(int) * WORK_SIZE, cudaMemcpyDeviceToHost));
for (i = 0; i < WORK_SIZE; i )
printf("Input value: %d n", a_h[i] );
CUDA_CHECK_RETURN(cudaFree((void*) a_d));
CUDA_CHECK_RETURN(cudaDeviceReset());
return 0;
}
flags.h
#ifndef FLAGS_H_
#define FLAGS_H_
#include "square_.cu"
#define CUDA_CHECK_RETURN(value) {
cudaError_t _m_cudaStat = value;
if (_m_cudaStat != cudaSuccess) {
fprintf(stderr, "Error %s at line %d in file %sn",
cudaGetErrorString(_m_cudaStat), __LINE__, __FILE__);
exit(1);
} }
#define WORK_SIZE 29
#endif /* FLAGS_H_ */
square_.cu
__global__ void sq_array( int *a) {
int idx = blockIdx.x * blockDim.x threadIdx.x;
if (idx< WORK_SIZE) a[idx] = a[idx] * a[idx];
}
Комментарии:
1. Вы
#include
редактируете.cu
файл и компилируете.cu
файл, что означает, что у вас будет два определенияsq_array
. Когда он компилируется отдельно, определение файла заголовкаWORK_SIZE
не указано. Не включайте файлы.cu
или.c
— компилируйте отдельно и связывайте. Вам нужно организовать все так, чтобыsq_array
и вызов ядра находились в одном файле, который компилируется один раз.2. @wcocharan Я надеюсь, что это должен быть процесс сборки в один клик, потому что он работает в терминале с помощью команды make в одну строку. Это короткий код, объясняющий мою проблему, но мой реальный код длинный и сложный с десятками ядер, поэтому я не могу поместить вызов ядра и определение ядра в один файл, как вы предложили. Кроме того, когда у меня есть десятки файлов, компилировать и связывать их по отдельности будет довольно утомительно. будет полезно посмотреть какое-нибудь видео на YouTube.
3. Это работает в командной строке, потому что вы явно не компилируете
.cu
файл, но IDE это сделает. Вы должны организовать все по-другому. Я работаю над массивными кодовыми базами, которые используют CUDA, и наша обычная стратегия заключается в создании функций «оболочки хоста», которые инкапсулируют код ядра CUDA и вызов. Использование#include "square_.cu"
— это просто плохая идея — (вы бы не стали делать этого с.c
файлом) — каждый фрагмент отдельно скомпилированного кода, который включаетflags.h
, будет определять еще одну версиюsq_array
функции.4. можете ли вы опубликовать решение, не помещая весь код в один файл? Я опубликовал эту простую проблему здесь, чтобы понять, как «собрать» большой код (разбитый на несколько файлов) в Nsight IDE.
Ответ №1:
Проблема в том, что ваша среда разработки компилируется square_.cu
и компилируется main.cu
, которая также компилируется square_.cu
снова из-за #include "square_.cu"
in flags.h
, который дает вам два определения sq_array
. При square_.cu
компиляции WORK_SIZE
макрос не определен, что приводит к ошибке во время компиляции. При компиляции в командной строке вы не компилировались square_.cu
, поэтому вы избежали этой ошибки.
В любом случае, это плохая идея для #include
.cu
(или .c
файлов). Они должны быть скомпилированы отдельно, а затем связаны вместе.
Вы должны организовать вещи по-другому. Я не знаю деталей вашего кода, но вы можете сделать что-то вроде этого:
square.cu
:
#include "square.h"
__global__ void sq_array( int *a) {
int idx = blockIdx.x * blockDim.x threadIdx.x;
if (idx< WORK_SIZE) a[idx] = a[idx] * a[idx];
}
void host_sq_array(int *a_d) {
int block_size = 4;
int n_blocks = WORK_SIZE/block_size (WORK_SIZE%block_size == 0 ? 0:1);
sq_array<<<n_blocks, block_size>>>(a_d);
}
square.h
:
#ifndef SQUARE_H
#define SQUARE_H
#include "flags.h" // REMOVE #include of .cu file!!!
void host_sq_array(int *a_d);
#endif
Вы можете безопасно #include square.h
включать только константы, определения типов и прототипы функций.