CUDA 踩坑日记

2021.4.2

  1. gpu的内存需要gpu来操作
int main()
{
  int* dev_1,dev_2;
  cudaMalloc((void**)&dev_1,sizeof(int)*100);
  cudaMalloc((void**)&dev_2,sizeof(int)*100);
  //下面是错误的
  dev_1[0]=dev_2[0];//dev_1和dev_2都是gpu内存,所以这个操作(读/写)cpu干不了,需要让gpu来干。
}
  1. kernal中分配不了大内存
__global__ void test_kernal()
{
  int* dev_1;
  //下面这个是错误的,因为你要的东西太大了。
  auto cudaStatus = cudaMalloc((void**)&dev_1,sizeof(int)*100000000);
}

2021.4.14

  1. kernal中for循环有大小限制
__global__ void test_kernal()
{
  for(int i=0;i<100000;i++)//很有可能会运行错误!这个大小限制不是固定的,是跟代码量相关的。
  {
    //...
  }
}
  1. kernal中调用其他kernal,也是有限制的
__global__ void t1_kernal()
{
 //... 
}
__global__ void t2_kernal()
{
  t1_kernal<<<1024,1024>>>();
}
__global__ void main_kernal()
{
  t2_kernal<<<1024,1024>>>();
}
void main()
{
  main_kernal<<<1024,1024>>>();//这里大概率会运行错误,我猜是线程数量太多了。
}
  1. 关于线性插值
%Matlab代码
%其中x_src是一维数组,y_src是二维数组,x_dest是一维数组,y_dest是输出结果
y_dest=interp1(x_src,y_src,x_dest,'linear');
//我的建议是,先处理x_src和x_dest,将其转换为对应下标和比值
//src是x_src,dest是x_dest,indexs是输出的对应下标,ratios是输出的比值,size是dest数组的大小
__host__ void interp1_prepare(float *src, float *dest, int *indexs, float *ratios, int size)
{
    int src_index = 0;
    float src_min = src[src_index];
    float src_max = src[src_index + 1];
    for (int i = 0; i < size; i++)
    {
        float now_dest = dest[i];
        while (true)
        {
            if ((now_dest - src_min) * (now_dest - src_max) <= 0) //两者之间
            {
                break;
            }
            else if ((src_index == 0 || src_index == size - 2) && ((now_dest <= src_min && src_min < src_max) || (now_dest >= src_min && src_min > src_max))) //在两端情况下,
            {
                break;
            }
            if (src_index < size - 1)
            {
                src_index++;
                src_min = src[src_index];
                src_max = src[src_index + 1];
            }
            else
            {
                break;
            }
        }
        indexs[i] = src_index;
        ratios[i] = (now_dest - src_min) / (src_max - src_min);
    }
}
int x_src[3]={1,2,4};
int x_dest[3]={1.1,2.3,3.5};
int indexs[3];
int ratios[3];
interp1_prepare(x_src,x_dest,indexs,ratios,3);
//indexs结果为:{0,1,1}
//ratios结果为:{0.1,0.15,0.75}
//这是数据的前处理,实在cpu中进行的,下面可以放到gpu中
//这是核函数
//indexs,ratios就是数据前处理时的准备好的数据
//src就是y_src
//dest就是y_dest
//row_length和col_length用来描述src/dest大小
//size就是src/dest的长度,等于row_length*col_length
__global__ void interp1_liear_kernal(int *indexs, float *ratios, float *src, float *dest, int row_length,int col_length, int size)
{
    //先求数组下标,这部分是固定的
    int all_blocks = gridDim.x * gridDim.y * blockIdx.z + gridDim.x * blockIdx.y + blockIdx.x;
    int block_threads = blockDim.x * blockDim.y * threadIdx.z + blockDim.x * threadIdx.y + threadIdx.x;
    int loc = all_blocks * (blockDim.x * blockDim.y * blockDim.z) + block_threads;
    //判断有没有超界
    if (loc < size)
    {
        //从1维坐标转换到2维坐标,为什么row不是loc%col_length?
        //这个是为了和matlab里面的1维转2维保持一致。
        //在matlab中,[1,2,3,4]转成2维就是[[1,3],[2,4]]
        int row = loc % row_length;
        int col = loc / row_length;
        int src_index = indexs[row];
        float src_ratio = ratios[row];
        float src_min = src[col*row_length+src_index];//等同二维的src[src_index,col]
        float src_max = src[col*row_length+src_index+1];//等同二维的src[src_index+1,col]
        dest[col*row_length+row] = src_min + src_ratio * (src_max - src_min);
    }
}
//下面就是调用核函数来线性插值
//indexs_gpu是将cpu中的indexs复制到gpu中的结果
//ratios_gpu,y_src_gpu同理
//y_dest_gpu是结果,也是gpu内存
//4,4是y_src_gpu和y_dest_gpu的二维大小
//16是y_src_gpu和y_dest_gpu的一维大小
interp1_liear_kernal<<<1,16>>>(indexs_gpu,ratios_gpu,y_src_gpu,y_dest_gpu,4,4,16);
  1. 用代码来描述NVIDIA GPU
//C#
//这是一种简单的描述方法
class GPU
{
  SM[] SM_Array;
  GlobalMemory Global_Memory;//全局内存、显存
}
//Streaming Multiprocessor 、流处理器簇 、流处理器组
class SM
{
  SP[192] SP_Array;//可能更多
  SharedMemory Shared_Memory;//共享内存
  int WrapSize=32;//这个可以暂时忽略,这是一个中间概念,没意思
  public void Run(Thread[] threads)
  {
    //下面会忽略WrapSize的概念
    for(int i=0;i<threads.Length;i+=SP_Array.Length)
    {
      for(int j=0;j<SP_Array.Length;j++)
      {
        SP_Array[j].Run(threads[i+j]);
      }
    }
  }
  public void Run(Block block)
  {
    Run(block.Threads);
  }
}
//Streaming Processor 、CUDA Core 、流处理器 、
class SP
{
  public void Run(Thread thread)
  {
    //执行当前的线程
  }
}

转载请标准来源:https://www.cnblogs.com/TidyScript/p/14611288.html

posted on 2021-04-02 16:25  TypeSharp  阅读(74)  评论(0编辑  收藏  举报

导航