2015-11-13 4 views
0

Я пытаюсь сделать расчет FFT плюс ядра. FFT: библиотека managedCUDA ядро ​​известково: собственное ядро ​​1D FFT плюс вычисление ядра с помощью управляемого CUDA

C# код

public void cuFFTreconstruct() { 
       CudaContext ctx = new CudaContext(0); 
       CudaKernel cuKernel = ctx.LoadKernel("kernel_Array.ptx", "cu_ArrayInversion"); 

       float[] fData = new float[Resolution * Resolution * 2]; 
       float[] result = new float[Resolution * Resolution * 2]; 
       CudaDeviceVariable<float> devData = new CudaDeviceVariable<float>(Resolution * Resolution * 2); 
       CudaDeviceVariable<float> copy_devData = new CudaDeviceVariable<float>(Resolution * Resolution * 2); 

       int i, j; 
       Random rnd = new Random(); 
       double avrg = 0.0; 

       for (i = 0; i < Resolution; i++) 
       { 
        for (j = 0; j < Resolution; j++) 
        { 
         fData[(i * Resolution + j) * 2] = i + j * 2; 
         fData[(i * Resolution + j) * 2 + 1] = 0.0f; 
        } 
       } 

       devData.CopyToDevice(fData); 

       CudaFFTPlan1D plan1D = new CudaFFTPlan1D(Resolution * 2, cufftType.C2C, Resolution * 2); 
       plan1D.Exec(devData.DevicePointer, TransformDirection.Forward); 

       cuKernel.GridDimensions = new ManagedCuda.VectorTypes.dim3(Resolution/256, Resolution, 1); 
       cuKernel.BlockDimensions = new ManagedCuda.VectorTypes.dim3(256, 1, 1); 

       cuKernel.Run(devData.DevicePointer, copy_devData.DevicePointer, Resolution); 

       devData.CopyToHost(result); 

       for (i = 0; i < Resolution; i++) 
       { 
        for (j = 0; j < Resolution; j++) 
        { 
         ResultData[i, j, 0] = result[(i * Resolution + j) * 2]; 
         ResultData[i, j, 1] = result[(i * Resolution + j) * 2 + 1]; 
        } 
       } 
       ctx.FreeMemory(devData.DevicePointer); 
       ctx.FreeMemory(copy_devData.DevicePointer); 
      } 

код ядра

//Includes for IntelliSense 
    #define _SIZE_T_DEFINED 
    #ifndef __CUDACC__ 
    #define __CUDACC__ 
    #endif 
    #ifndef __cplusplus 
    #define __cplusplus 
    #endif 


    #include <cuda.h> 
    #include <device_launch_parameters.h> 
    #include <texture_fetch_functions.h> 
    #include "float.h" 
    #include <builtin_types.h> 
    #include <vector_functions.h> 

    // Texture reference 
    texture<float2, 2> texref; 

    extern "C" 
    { 
     __global__ void cu_ArrayInversion(float* data_A, float* data_B, int Resolution) 
     { 
      int image_x = blockIdx.x * blockDim.x + threadIdx.x; 
      int image_y = blockIdx.y; 

      data_B[(Resolution * image_x + image_y) * 2] = data_A[(Resolution * image_y + image_x) * 2]; 
      data_B[(Resolution * image_x + image_y) * 2 + 1] = data_A[(Resolution * image_y + image_x) * 2 + 1]; 
     } 
    } 

Однако эта программа не работает. Произошла ошибка:

ОшибкаLaunchFailed: Исключение произошло на устройстве во время выполнения ядра. Распространенные причины включают разыменование недопустимого указателя устройства и доступ к нераспределенной общей памяти. Контекст нельзя использовать, поэтому он должен быть уничтожен (и должен быть создан новый). Все существующие распределения памяти устройства из этого контекста являются недопустимыми и должны быть восстановлены, если программа продолжит использовать CUDA.

ответ

0

Спасибо за сообщение.

хост код

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Drawing.Imaging; 
using ManagedCuda; 
using ManagedCuda.CudaFFT; 
using ManagedCuda.VectorTypes; 


namespace WFA_CUDA_FFT 
{ 
    public partial class CuFFTMain : Form 
    { 
     float[, ,] FFTData2D; 
     int Resolution; 

     const int cuda_blockNum = 256; 

     public CuFFTMain() 
     { 
      InitializeComponent(); 
      Resolution = 1024; 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      cuFFTreconstruct(); 
     } 
     public void cuFFTreconstruct() 
     { 
      CudaContext ctx = new CudaContext(0); 
      ManagedCuda.BasicTypes.CUmodule cumodule = ctx.LoadModule("kernel.ptx"); 
      CudaKernel cuKernel = new CudaKernel("cu_ArrayInversion", cumodule, ctx); 
      float2[] fData = new float2[Resolution * Resolution]; 
      float2[] result = new float2[Resolution * Resolution]; 
      FFTData2D = new float[Resolution, Resolution, 2]; 
      CudaDeviceVariable<float2> devData = new CudaDeviceVariable<float2>(Resolution * Resolution); 
      CudaDeviceVariable<float2> copy_devData = new CudaDeviceVariable<float2>(Resolution * Resolution); 

      int i, j; 
      Random rnd = new Random(); 
      double avrg = 0.0; 

      for (i = 0; i < Resolution; i++) 
      { 
       for (j = 0; j < Resolution; j++) 
       { 
        fData[i * Resolution + j].x = i + j * 2; 
        avrg += fData[i * Resolution + j].x; 
        fData[i * Resolution + j].y = 0.0f; 
       } 
      } 

      avrg = avrg/(double)(Resolution * Resolution); 

      for (i = 0; i < Resolution; i++) 
      { 
       for (j = 0; j < Resolution; j++) 
       { 
        fData[(i * Resolution + j)].x = fData[(i * Resolution + j)].x - (float)avrg; 
       } 
      } 

      devData.CopyToDevice(fData); 

      CudaFFTPlan1D plan1D = new CudaFFTPlan1D(Resolution, cufftType.C2C, Resolution); 
      plan1D.Exec(devData.DevicePointer, TransformDirection.Forward); 

      cuKernel.GridDimensions = new ManagedCuda.VectorTypes.dim3(Resolution/cuda_blockNum, Resolution, 1); 
      cuKernel.BlockDimensions = new ManagedCuda.VectorTypes.dim3(cuda_blockNum, 1, 1); 

      cuKernel.Run(devData.DevicePointer, copy_devData.DevicePointer, Resolution); 

      copy_devData.CopyToHost(result); 

      for (i = 0; i < Resolution; i++) 
      { 
       for (j = 0; j < Resolution; j++) 
       { 
        FFTData2D[i, j, 0] = result[i * Resolution + j].x; 
        FFTData2D[i, j, 1] = result[i * Resolution + j].y; 
       } 
      } 

      //Clean up 
      devData.Dispose(); 
      copy_devData.Dispose(); 
      plan1D.Dispose(); 
      CudaContext.ProfilerStop(); 
      ctx.Dispose(); 
     } 
    } 
} 

код ядра

//Includes for IntelliSense 
#define _SIZE_T_DEFINED 
#ifndef __CUDACC__ 
#define __CUDACC__ 
#endif 
#ifndef __cplusplus 
#define __cplusplus 
#endif 


#include <cuda.h> 
#include <device_launch_parameters.h> 
#include <texture_fetch_functions.h> 
#include "float.h" 
#include <builtin_types.h> 
#include <vector_functions.h> 
#include <vector> 

// Texture reference 
texture<float2, 2> texref; 

extern "C" 
{ 
    // Device code 

    __global__ void cu_ArrayInversion(float2* data_A, float2* data_B, int Resolution) 
    { 
     int image_x = blockIdx.x * blockDim.x + threadIdx.x; 
     int image_y = blockIdx.y; 

     data_B[(Resolution * image_x + image_y)].y = data_A[(Resolution * image_y + image_x)].x; 
     data_B[(Resolution * image_x + image_y)].x = data_A[(Resolution * image_y + image_x)].y; 
    } 
} 

Сначала я скомпилирован с .Net4.5. Эта программа не работает, и была показана ошибка (System.BadImageFormatException). Однако, когда функция FFT игнорируется, запускается программа ядра.

Второе, что я передал от .Net 4.5 до .Net 4.0. Функция FFT работает, но ядро ​​не запускается и показывает ошибки.

Мой компьютер окна 8,1 про и я использую Visual Studio 2013.

2

FFT-план принимает количество элементов, то есть число комплексных чисел, в качестве аргумента. Поэтому удалите * 2 в первом аргументе конструктора плана. И раз два для числа партий также не имеет смысла ...

Далее я бы использовал float2 или cuFloatComplex тип (в ManagedCuda.VectorTypes) для представления комплексных чисел, а не два сырых поплавков. Чтобы освободить память, используйте методы Dispose для CudaDeviceVariable. В противном случае он позже будет называться GC.

код хоста будет выглядеть примерно так:

int Resolution = 512; 
CudaContext ctx = new CudaContext(0); 
CudaKernel cuKernel = ctx.LoadKernel("kernel.ptx", "cu_ArrayInversion"); 

//float2 or cuFloatComplex 
float2[] fData = new float2[Resolution * Resolution]; 
float2[] result = new float2[Resolution * Resolution]; 
CudaDeviceVariable<float2> devData = new CudaDeviceVariable<float2>(Resolution * Resolution); 
CudaDeviceVariable<float2> copy_devData = new CudaDeviceVariable<float2>(Resolution * Resolution); 

int i, j; 
Random rnd = new Random(); 
double avrg = 0.0; 

for (i = 0; i < Resolution; i++) 
{ 
for (j = 0; j < Resolution; j++) 
{ 
    fData[(i * Resolution + j)].x = i + j * 2; 
    fData[(i * Resolution + j)].y = 0.0f; 
} 
} 

devData.CopyToDevice(fData); 

//Only Resolution times in X and Resolution batches 
CudaFFTPlan1D plan1D = new CudaFFTPlan1D(Resolution, cufftType.C2C, Resolution); 
plan1D.Exec(devData.DevicePointer, TransformDirection.Forward); 

cuKernel.GridDimensions = new ManagedCuda.VectorTypes.dim3(Resolution/256, Resolution, 1); 
cuKernel.BlockDimensions = new ManagedCuda.VectorTypes.dim3(256, 1, 1); 

cuKernel.Run(devData.DevicePointer, copy_devData.DevicePointer, Resolution); 

devData.CopyToHost(result); 

for (i = 0; i < Resolution; i++) 
{ 
    for (j = 0; j < Resolution; j++) 
    { 
     //ResultData[i, j, 0] = result[(i * Resolution + j)].x; 
     //ResultData[i, j, 1] = result[(i * Resolution + j)].y; 
    } 
} 

//And better free memory using Dispose() 
//ctx.FreeMemory is only meant for raw device pointers obtained from somewhere else... 
devData.Dispose(); 
copy_devData.Dispose(); 
plan1D.Dispose(); 
//For Cuda Memory checker and profiler: 
CudaContext.ProfilerStop(); 
ctx.Dispose(); 
+0

Пожалуйста, пост также обновленный код хоста или дважды проверьте, что оно соответствует приведенному выше коду. Если я позволю обеим вашим ядрам работать с кодом хоста, который я разместил здесь, все работает нормально. Cuda Memory Checker не находит ничего и не сообщает об ошибке. – kunzmi

+0

Благодарим вас за комментарии. Я проверил свой код. Однако я не мог найти ошибку. Моя программа была сделана ссылкой на сайты: (setup: https://managedcuda.codeplex.com/documentatio, dll: https://github.com/kunzmi/managedCuda, пример кода: https://github.com/ kunzmi/managedCuda). Когда я делаю 2D cuda и 1D cuda с managedCUDA, программы работают хорошо, и я могу получить хороший результат FFT. – test

+0

Пожалуйста, разместите свой код хоста точно так же, как вы его используете, чтобы можно было воспроизвести вашу проблему. Снова: код хоста, который я разместил выше, работает без проблем вместе с вашими ядрами, поэтому разница должна быть разной. – kunzmi

0

Спасибо за это предложение.

Я пробовал предлагаемый код. Однако ошибка осталась. (ошибка: ErrorLaunchFailed: Исключение произошло на устройстве во время выполнения ядра.Основные причины включают в себя разыменование недопустимого указателя устройства и доступ к внешней памяти без ограничений. Контекст нельзя использовать, поэтому он должен быть уничтожен (а новый должен быть будет создано). Все существующие распределения памяти устройства из этого контекста, являются недействительными и должны быть восстановлены, если программа будет продолжаться с использованием CUDA.)

чтобы использовать float2, я изменил код у.е. следующего

extern "C" 
{ 

__global__ void cu_ArrayInversion(float2* data_A, float2* data_B, int Resolution) 
    { 
    int image_x = blockIdx.x * blockDim.x + threadIdx.x; 
    int image_y = blockIdx.y; 

    data_B[(Resolution * image_x + image_y)].x = data_A[(Resolution * image_y + image_x)].x; 
    data_B[(Resolution * image_x + image_y)].y = data_A[(Resolution * image_y + image_x)].y; 
} 

Когда программа выполняет «cuKernel.Run», процесс останавливается.

PTX файл

.version 4.3 
.target sm_20 
.address_size 32 

    // .globl cu_ArrayInversion 
.global .texref texref; 

.visible .entry cu_ArrayInversion(
    .param .u32 cu_ArrayInversion_param_0, 
    .param .u32 cu_ArrayInversion_param_1, 
    .param .u32 cu_ArrayInversion_param_2 
) 
{ 
    .reg .f32 %f<5>; 
    .reg .b32 %r<17>; 


    ld.param.u32 %r1, [cu_ArrayInversion_param_0]; 
    ld.param.u32 %r2, [cu_ArrayInversion_param_1]; 
    ld.param.u32 %r3, [cu_ArrayInversion_param_2]; 
    cvta.to.global.u32 %r4, %r2; 
    cvta.to.global.u32 %r5, %r1; 
    mov.u32  %r6, %ctaid.x; 
    mov.u32  %r7, %ntid.x; 
    mov.u32  %r8, %tid.x; 
    mad.lo.s32 %r9, %r7, %r6, %r8; 
    mov.u32  %r10, %ctaid.y; 
    mad.lo.s32 %r11, %r10, %r3, %r9; 
    shl.b32  %r12, %r11, 3; 
    add.s32  %r13, %r5, %r12; 
    mad.lo.s32 %r14, %r9, %r3, %r10; 
    shl.b32  %r15, %r14, 3; 
    add.s32  %r16, %r4, %r15; 
    ld.global.v2.f32 {%f1, %f2}, [%r13]; 
    st.global.v2.f32 [%r16], {%f1, %f2}; 
    ret; 
} 
Смежные вопросы