2021.4.2
- 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来干。
}
- kernal中分配不了大内存
__global__ void test_kernal()
{
int* dev_1;
//下面这个是错误的,因为你要的东西太大了。
auto cudaStatus = cudaMalloc((void**)&dev_1,sizeof(int)*100000000);
}
2021.4.14
- kernal中for循环有大小限制
__global__ void test_kernal()
{
for(int i=0;i<100000;i++)//很有可能会运行错误!这个大小限制不是固定的,是跟代码量相关的。
{
//...
}
}
- 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>>>();//这里大概率会运行错误,我猜是线程数量太多了。
}
- 关于线性插值
%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);
- 用代码来描述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