首页 > 系统相关 >yolov5内存分布分析

yolov5内存分布分析

时间:2023-05-30 13:57:02浏览次数:46  
标签:yolov5 sigmoid float cell pindex 分布 内存 boundingbox anchor

yolov5内存分布分析

Transpose输出分析

假设batch_size为1,yolov5有三个输出,shape分别是:

  • (1,3,80,80,85)
  • (1,3,40,40,85)
  • (1,3,20,20,85)

其中3代表anchor数量,20*20代表feature_map大小,85代表boundbox的(x,y,w,h,c+80个类别的概率)

其中(x,y,w,h,c+80个类别的概率)在内存中是连续分布的,即:

(1,3,20,20,85)整个数组在内存分布中也是连续分布的,

  • (0,0,0,0,0)->x->第一个anchor在第一个cell对应的boundingbox的x
  • (0,0,0,0,1)->y->第一个anchor在第一个cell对应的boundingbox的y
  • (0,0,0,0,2)->w->第一个anchor在第一个cell对应的boundingbox的w
  • (0,0,0,0,3)->h->第一个anchor在第一个cell对应的boundingbox的h
  • ​ ......
  • (0,0,0,1,0)->x->第一个anchor在第二个cell对应的boundingbox的x
  • (0,0,0,1,1)->y->第一个anchor在第二个cell对应的boundingbox的y
  • (0,0,0,1,2)->w->第一个anchor在第二个cell对应的boundingbox的w
  • (0,0,0,1,3)->h->第一个anchor在第二个cell对应的boundingbox的h
  • ......
  • (0,1,0,0,0)->x->第二个anchor在第一个cell对应的boundingbox的x
  • (0,1,0,0,1)->y->第二个anchor在第一个cell对应的boundingbox的y
  • (0,1,0,0,2)->w->第二个anchor在第一个cell对应的boundingbox的w
  • (0,1,0,0,3)->h->第二个anchor在第一个cell对应的boundingbox的h

即:

后处理代码分析

# 从第一个anchor开始获取
for (int q = 0; q < num_anchors; q++)
    {
        const float anchor_w = anchors[q * 2];
        const float anchor_h = anchors[q * 2 + 1];

        const ncnn::Mat feat = feat_blob.channel(q);
    
        #从第一个cell开始获取
        for (int i = 0; i < num_grid_y; i++)
        {
            for (int j = 0; j < num_grid_x; j++)
            {
                const float* featptr = feat.row(i * num_grid_x + j);
                #第5个是box_confidence值,需要使用sigmoid函数求值
                float box_confidence = sigmoid(featptr[4]);
                if (box_confidence >= prob_threshold)
                {
                    # 之所以这么写是因为可以减少sigmoid(class_score)的次数,sigmoid较为耗时
                    #find class index with max class score
                    int class_index = 0;
                    float class_score = -FLT_MAX;
                    for (int k = 0; k < num_class; k++)
                    {
                        # box_confidence之后是每个类别的概率
                        float score = featptr[5 + k];
                        if (score > class_score)
                        {
                            class_index = k;
                            class_score = score;
                        }
                    }
                    #论文规定
                    float confidence = box_confidence * sigmoid(class_score);
                    if (confidence >= prob_threshold)
                    {
                        # 依次获取x,y,w,h
                        float dx = sigmoid(featptr[0]);
                        float dy = sigmoid(featptr[1]);
                        float dw = sigmoid(featptr[2]);
                        float dh = sigmoid(featptr[3]);
    					
                        # 其余部分省略,可以参考ncnn代码
                        .......
   
                    }
                }
            }
        }
    }

====================================================================================

Conv输出分析

NPU对算法进行加速处理时,shape算子,如reshape、transpose通常不支持加速,有两种解决方法,

  • 使用C/C++语言重新实现reshape、transpose算子功能,使用CPU进行处理(待完善)
  • 直接按照conv层的输出内存分布获取数据进行处理

假设batch_size为1,卷积层的输出shape为:

  • (1,255,80,80)
  • (1,255,40,40)
  • (1,255,20,20)

其中255表示3*85,3代表anchor数量,,85代表boundbox的(x,y,w,h,c+80个类别的概率),20x20代表feature_map大小。

其中(x,y,w,h,c+80个类别的概率)在内存中是连续分布的,即:

(1,255,20,20)整个数组在内存分布中也是连续分布的,

  • (0,0,0,0)->x->第一个anchor在第一个cell对应的boundingbox的x

  • (0,0,0,1)->x->第一个anchor在第二个cell对应的boundingbox的x

  • (0,0,0,2)->x->第一个anchor在第三个cell对应的boundingbox的x

  • ......

  • (0,1,0,0)->x->第一个anchor在第一个cell对应的boundingbox的y

  • (0,1,0,1)->x->第一个anchor在第二个cell对应的boundingbox的y

  • (0,1,0,2)->x->第一个anchor在第三个cell对应的boundingbox的y

  • ......

  • (0,85,0,0)->x->第一个anchor在第一个cell对应的boundingbox的y

  • (0,85,0,1)->x->第二个anchor在第二个cell对应的boundingbox的y

  • (0,85,0,2)->x->第二个anchor在第三个cell对应的boundingbox的y

  • ....

    即:

后处理代码分析

# 从第一个cell开始
for(int shiftY = 0; shiftY < gridY; shiftY++)
	{
		for(int shiftX = 0; shiftX < gridX; shiftX++)
		{
                        # 从第一个anchor开始
			for(int i = 0; i < 3; i++)
			{
				pRecord = pMatData[i];
				# 获取当前cell
				int pindex = shiftY* gridX + shiftX;
				# coordindex的坐标对应x
                                int coordindex = pindex;
                                # 指针移动到y
				pindex = pindex + gridX * gridY;
				# 指针移动到w
                                pindex = pindex + gridX * gridY;
				# 指针移动到h
                                pindex = pindex + gridX * gridY;
				# 指针移动到C
                                pindex = pindex + gridX * gridY;
				# 获取C的值
				float  precord4 = sigmoid(pRecord[pindex]);
				# 指针移动到P
                                pindex = pindex + gridX * gridY ;
	
				for (cls = 0; cls < classNum; cls++)
				{
					#获取P的值
					float  precord5 = sigmoid(pRecord[pindex]);
					#指针移动到P1
                                         pindex = pindex + gridX * gridY;
	
					score = precord5 * precord4;

	
					if (score > gYolov7Para.confidenceThreshold)
					{//大于设置的阈值
						# 获取x
						float  precord0 = sigmoid(pRecord[coordindex]);
						coordindex = coordindex + gridX * gridY;
						# 获取y	
                     	                        float  precord1 = sigmoid(pRecord[coordindex]);
						coordindex = coordindex + gridX * gridY;
						# 获取w	
                     	                        float  precord2 = sigmoid(pRecord[coordindex]);
						coordindex = coordindex + gridX * gridY;
						# 获取h	
                     	                        float  precord3 = sigmoid(pRecord[coordindex]);
						coordindex = coordindex + gridX * gridY;
						# 其余部分省略
                        .......
					}
	
				}
			}
		}
	}

标签:yolov5,sigmoid,float,cell,pindex,分布,内存,boundingbox,anchor
From: https://www.cnblogs.com/LuckCoder/p/17443014.html

相关文章

  • 检测CPU,内存,磁盘使用率shell
    检测CPU,内存,磁盘使用率shell 1.检测CPU,内存,磁盘使用率超过80%,则发送邮件告警#!/bin/bash#当前主机ipHOST=$(ipashoweth0|grep'\inet\b'|awk'{print$2}'|sed's/\/.*//')#告警邮箱[email protected]#磁盘使用百分比阈值DISK_USAGE_THRESHOLD=80#CPU......
  • 新版本Edge浏览器如何查看每一个网页的内存占用和cpu使用情况
       ......
  • 驱动开发:内核读写内存浮点数
    如前所述,在前几章内容中笔者简单介绍了内存读写的基本实现方式,这其中包括了CR3切换读写,MDL映射读写,内存拷贝读写,本章将在如前所述的读写函数进一步封装,并以此来实现驱动读写内存浮点数的目的。内存浮点数的读写依赖于读写内存字节的实现,因为浮点数本质上也可以看作是一个字节集,对......
  • Redis+分布式+秒杀
    聊一下MySQL关于mysql关系型数据库的一些分析:1、从性能上:如果我们碰到需要执行耗时特别久,并且执行结果不是很频繁变动的SQL语句,我们就没有必要每次都去查询数据库,因为每次操作数据库都很耗时。2、从并发上:在大并发的情况下(比如618秒杀活动,你敢让千万级的请求直接打到数据库上吗......
  • 十、JUC-Java对象内存布局和对象头
    零、问题Objectobject=newObject()谈谈你对这句话的理解?一般而言JDK8按照默认情况下,new一个对象占多少内存空间?位置所在:JVM里堆→新生区→伊甸园区一、对象的内存布局在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头、实例数据、对齐填充(保证8......
  • JNI-记录一个内存泄露的问题
    android:channelisunrecoverablybrokenandwillbedisposed记录一个关于内存泄漏的问题:RT,在停止播放音乐时,每过一段时间就会报05-2510:52:21.125491-528/system_processE/InputDispatcher:channel'4a8b59f4activity.MainActivity(server)'~Channelisun......
  • JVM运行时的数据区 (内存溢出实例)
    一、概述运行时数据区是jvm运行时的内存布局,类装载到内存后存放的位置,为执行引擎提供所需指令和数据。运行时数据区包括:堆、栈、方法区、本地方法栈、pc计数器。接下来会详细介绍各个部分,并介绍直接内存访问和方法区中的常量池,另外对于每个区域可能发生的内存异常用demo做讲解。二......
  • 聊聊分布式解决方案Saga模式
    Saga模式Saga模式使用一系列本地事务来提供事务管理,而一个本地事务对应一个Saga参与者,在Saga流程里面每一个本地事务只操作本地数据库,然后通过消息或事件来触发下一个本地事务,如果其中一个本地事务失败了,Saga就会执行一系列补偿事务来实现回滚操作。(补偿事务简单来讲就是对之前本......
  • Java内存溢出和内存泄露
    一、为什么要了解内存泄露和内存溢出? 1、内存泄露一般是代码设计存在缺陷导致的,通过了解内存泄露的场景,可以避免不必要的内存溢出和提高自己的代码编写水平;2、通过了解内存溢出的几种常见情况,可以在出现内存溢出的时候快速的定位问题的位置,缩短解决故障的时间。 二、基本概念 内......
  • Java 内存模型及GC原理
    一个优秀Java程序员,必须了解Java内存模型、GC工作原理,以及如何优化GC的性能、与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统、实时系统等,只有全面提升内存的管理效率,才能提高整个应用程序的性能。本文将从JVM内存模型、GC工作原理,以及GC的几个关键问题进行探讨,从G......