Cuda & amp; cublas: вызов глобальной функции после использования cublas

Я пишу программу, включающую умножение матрицы на вектор и решение наименьших квадратов, используя кублы & Cula API. Программа будет повторяться много раз. на каждом шаге я должен установить конкретную строку одной матрицы на ноль.

Я попытался скопировать всю матрицу (50 * 1000 или более) в процессор и установить одну строку в ноль, а затем скопировать матрицу обратно, но это слишком много времени, потому что программа будет повторяться 10 или более раз. Поэтому я решил написать функцию ядра.

Глобальная функция, как это:

__global__ void Setzero(float* A, int index) /* A is the matrix and in col-major , index is the row I want to set zero */
{
int ind=blockDim.x*blockIdx.x+threadIdx.x;
if( ((ind%N)==index ) && (ind<50000) )  //notice matrix is in col-major ,matrix size is 50000
{
A[ind]=0.0;
ind+=blockDim.x*blockIdx.x;
}
else    ;
__syncthreads();
}

Вопрос в том, когда я делаю это (используйте cublas перед вызовом функции):

cudaMalloc((void**)&A_Gpu_trans,sizeof(float)*50000);
cudaMemcpy(A_Gpu_trans,A_trans,sizeof(float)*M*N,cudaMemcpyHostToDevice);
cublasSgemv_v2(handle,CUBLAS_OP_N,1000,50,&al,A_Gpu_trans,1000,err_gpu,1,&beta,product,1);
dim3 dimBlock(16,1);
dim3 dimGrid((50000-1)/16+1,1);
Setzero<<<dimGrid,dimBlock>>>(A_Gpu_trans,Index);

Вернуть ошибку:

a __host__ function("Setzero") redeclared with __global__.

и другая ошибка:

MSB3721: команда «» C: \ Program Files \ NVIDIA GPU Computing
Инструментарий \ CUDA \ v5.5 \ bin \ nvcc.exe «-gencode = arch = compute_10, code = \» sm_10, compute_10 \ «—use-local-env —cl-версия 2010 -ccbin» D: \ Program Файлы \ Microsoft Visual Studio 10.0 \ VC \ bin «-I» C: \ Program Files \ Набор инструментов для вычислений на GPU NVIDIA \ CUDA \ v5.5 \ включают «-I» C: \ Program Files \ Вычисления на GPU NVIDIA
Инструментарий \ CUDA \ v5.5 \ include «-G —keep-dir Debug -maxrregcount = 0
—machine 32 — Компилировать -cudart static -g -DWIN32 -D_DEBUG -D_CONSOLE -D_MBCS -Xcompiler «/ EHsc / W3 / nologo / Od / Zi / RTC1 / MDd» -o Debug \ kernel.cu.obj «C: \ Users \ Администратор \ Documents \ visual studio 2010 \ Проекты \ OOmp \ OOmp \ kernel.cu «” return 2。

Странно, когда я использую только cublas & API Cula Я могу получить правильный ответ.

0

Решение

Хотя вы не указали это в своем вопросе, у вас явно есть другая функция хоста, которая называется Setzero где-то в вашем коде. Простое решение — переименовать ядро ​​во что-то другое.

Основная причина, почему набор инструментов CUDA выдает ошибку, заключается в том, что Setzero<<< >>> Синтаксис вызова ядра в API времени выполнения заставляет интерфейсную часть CUDA создавать функцию хоста с тем же именем, что и у ядра с соответствующим списком аргументов, и заменять запуск ядра вызовом этой функции. Эта функция хоста содержит необходимые вызовы API для запуска ядра. Имея другую функцию хоста с тем же именем, что и у ядра, вы побеждаете этот процесс и вызываете ошибку компиляции, которую видите.

0

Другие решения

Кроме того, ваша функция является неправильной и дико неэффективной …

Вы не можете иметь вызов syncthread в таком условии, как это, это может привести к зависанию. Это также кажется совершенно ненужным здесь.

Более того, вы запускаете один поток для каждой записи матрицы, и только 1 / N из них действительно что-то делают.

Лучший подход — запускать только потоки, соответствующие записям, которые будут установлены на ноль. Что-то вроде этого:

__global__ void Setzero(float* A, int index)
{
int ind=blockDim.x*blockIdx.x+threadIdx.x;
if (ind < M)
A[index+N*ind]=0.0;
}

и вы запускаете M потоков (точнее, ceil (M / 256) потоковых блоков по 256 потоков каждый или любого размера блока, который вы хотите).

Например.:

int block_size = 256; // usually a good choice
int num_blocks = (M + block_size - 1) / block_size;
Setzero<<<num_blocks, block_size>>>(A, index);
1

По вопросам рекламы [email protected]