基于寒武纪平台的边缘智能实践课程-实验报告 2019.7.5
基于寒武纪平台的边缘智能实践课程-实验报告
2019.7.5
组员:林*港 16051518
组员:刘*文 16051519
分工:都做实验、都写报告
基本要求:
实验一
基础实验b01_opencv_conv
理解:这个程序调用了opencv的函数,进行了Laplacian卷积,提取到了边缘特征,对噪声敏感。
实验二
基础实验b02_selfdefine_conv:
理解:这个实验是手动实现图片的卷积,方法就是二次循环,滑动窗口计算。虽然卷积核是一样的Laplacian,但是输出结果和实验一有所不同,说明这个实现方法与opencv库函数不一样。
普通模糊blur
卷积核
[1,1,1]
[1,1,1]
[1,1,1]
忘记乘以1/9的结果,因为卷积的时候结果爆炸,超过了255的范围
[0.111,0.111,0.111]
[0.111,0.111,0.111]
[0.111,0.111,0.111] 普通模糊
还有高斯模糊等等这里就不做了。
实验三:
基础实验b03_cnml_conv
结果:
实验四
基础实验b04_cnrt_conv
可以看到寒武纪的运算速度比opencv软件实现的快多了,只用了2446us。而laplace算了1000次花了1.10253e+07us,即1.1*10^4us/次,大概是4.5倍,非常快。
扩展实验 e01_classification_alexnet
提高要求:
基于基础实验一,完成Sobel(索贝尔)算子得到支持
提示:需要对x方向和y方向分别计算后在合成
Sobel算子边缘检测
outputx
Outputy
Output=outputx+outputy
int main(int argc, char *argv[])
{
if(argc != 2) {
printf("wrong args\n");
std::cerr << "Usage:\n" << argv[0]
<< " input_image_path" << std::endl;
exit(0);
}
string image_path = argv[1];
Mat srcImage = imread(argv[1]);
Mat dst,dstx,dsty;
float time_use;
struct timeval tpend, tpstart;
gettimeofday(&tpstart, NULL);
// Laplacian边缘检测
// Laplacian(srcImage, dst, srcImage.depth(), 1);
//Sobel边缘检测
Sobel(srcImage, dstx, srcImage.depth(), 1,0,3);
Sobel(srcImage, dsty, srcImage.depth(), 0,1,3);
dst=dstx+dsty;
gettimeofday(&tpend, NULL);
time_use = 1000000 * (tpend.tv_sec - tpstart.tv_sec)
+ tpend.tv_usec - tpstart.tv_usec;
std::cout << "Forward execution time: "
<< time_use << " us" << std::endl;
imwrite("output.jpg", dst);
imwrite("outputx.jpg", dstx);
imwrite("outputy.jpg", dsty);
return 0;
}
拉普拉斯算子和苏泊尔算子的区别:
拉普拉斯算子是n维欧几里得空间中的一个二阶微分算子,定义为梯度的散度。
Sobel算子提取了x方向上的边界和y方向上的边界,然后将二张图片合成为一张图片
有多种合成方法,一种是sqrt(ux*ux+uy+uy),一种是ux+uy,这里我们为了方便直接使用了相加的办法。
扩展实验一 基于 AlexNet 网络模型的图像分类
数据流的分析:
//获取函数的 I/O 数据描述
cnrtGetInputDataDesc (&inputDescS , &inputNum , function);
cnrtGetOutputDataDesc(&outputDescS, &outputNum, function);
//在 CPU 内存上分配 I/O 数据空间并准备输入数据
inputCpuPtrS = (void**) malloc (sizeof(void*) * inputNum);
outputCpuPtrS = (void**) malloc (sizeof(void*) * outputNum);
Java写多了看c++有点不习惯,c++喜欢使用引用的方式改变值,这里把
基于扩展实验一,完成ResNet18的模型支持
复制一份e01到e03
使用grep命令查找所有含有alexnet字符串的文本文件
grep -rn “alexnet”
将所有”alexnet”的字符串替换为”resnet18”
还可以用sed命令直接替换所有的字符串 sed -i s/alexnet/resnet18/g `grep alexnet -rl ./`
这里为了避免错误,而且也比较少所以是手工改的。
先运行quantify.sh
再运行genoff.sh
再修改CMakeLists.txt 添加一个EXPR_E03_BIN
再运行build.sh
因为脚本要调用所在目录的model文件夹中的model,所以把输出到output文件夹的e03_classfication_resnet.bin复制到e03_classfication_resnet文件夹中。
输入图片:两个parachute和一个flag
Resnet
可以看到实验结果,准确度比原来的alexnet更高了
Alexnet
扩展实验二SSD
e02_detection_ssd
注意输入图片的格式不一定要256*256,程序会自动resize
实验中遇到的问题:
1、虚拟机网卡ping不通
因为使用的虚拟机软件是vmware player 15 找不到桥接模式的网卡设置(而vmware workstation有),所以我就把所有不相关的网卡全部禁用,这样就保证了使用的是GbE网卡
2、打字打错了,resnet打成了resxnet,使用grep命令查找文本文件中的字符串可以有效规避这种错误,提高效率。
3、挂载的时候mount 命令的 ip:全路径 即相对于根目录的路径而不是相对路径
mount -t nfs -o nolock -o tcp 172.19.24.200:${HOST_SDK_PATH} /mnt
4、FAT和FAT32的文件系统最大支持4GB的单个文件。文件读写是依靠FDT(file directory table)和FAT(file allocation table)来定位某一个文件的,FDT每一个表项32bit,所以文件最大不超过4G。u盘可以改为exFAT或者NTFS就可以支持更大的单个文件了。
感悟和理解:
边缘计算是指在靠近物或者数据源头的一侧,采用网络、计算、存储、应用核心能力为一体的开放平台,就近提供服务,它最大的优点就是响应速度快,其速度远远超过传统的云计算。寒武纪(Cambricon)芯片作为智能芯片的领先者,它的出现极大的促进了国内边缘计算的发展。寒武纪芯片的最大优点就是功耗低,发热小的同时性能达到了同时代的主流水平。
我们都知道深度学习分为两个过程,模型的构建和训练,模型的使用,前者耗费大量的计算资源,后者只需要少量的计算资源。通俗的来说比如y=kx+b,训练模型类似于一个拟合函数的过程(但是维度更高),求k 和b的时候过程很久,而当模型训练完毕,k b已知时输入x,那么y一下子就出来了,边缘计算就是基于这两个过程提出的,在本次实验中,模型就是k和b,构建出来的function是y=kx+b。本来常见的是训练和使用都用同一张显卡,在使用模型的时候会造成资源的浪费,边缘计算很好地解决了这个问题。只要在其他平台上使用大量的计算性能训练出模型,再使用专门的工具转化为适合该平台的模型,即可直接使用。
量化模型的好处有很多,简单的理解就是找近似值,把一个大的域映射到一个小的域,这有一点点像hash,比如把浮点数映射到整形值,比如1.98,2.01都可以映射到2。量化其实是一种权值共享的策略。比如有名的量化算法DeepCompression 主要分为三个主要的部分:剪枝,量化,哈夫曼编码。寒武纪作为一套边缘计算的平台,肯定要追求高实时性,高速度,高可靠性,低功耗,...量化模型以后运算量明显减少,可以大大提升效率。如果使用二值化神经网络BNN的量化方法的话,简单粗暴,因为只有0和1,运算效率大大提高。
硬件加速神经网络前向运算的最主要的任务就是完成卷积优化,减少卷积运算的资源和能源消耗非常核心。常见的方法有内存换取时间、乘法优化、GPU优化、卷积中的数据重用(权重固定、输出固定、NLR (No Local Reuse)、RS)