• GPU工作任务存储内存快动态调整兼顾效率


           VGS 是视频图形子系统,全称为 Video Graphics Sub-System。支持对一幅输入图像进行处理,如进行缩放、像素格式转换、视频存储格式转换、压缩/解压、打 COVER、打 OSD、画线、旋转、动态范围转换等处理。通常都是GPU来干的,以GPU要干一下用户指定的任务时是一批任务,每次需要完成的任务量又是不固定的,比如拿GPU来给一张输入图片做旋转、裁剪、拉伸、镜像、上下翻折、贴个LOGO、盖个色块、等操作,需要用一个内存块来记录一下这些任务。

    1. typedef struct _dsVGS_JOB_Task_S {
    2. GPU_NODE_WROK_TYPE_E enOpType;
    3. DS_S32 S32OsdNum;
    4. DS_S32 S32DrawLineNum;
    5. DS_S32 S32CoverNum;
    6. VGS_SCLCOEF_MODE_E enVgsSclCoefMode;
    7. ROTATION_E enRotationAngle;
    8. VGS_ADD_COVER_S *pstVgsAddCover;
    9. VGS_ADD_OSD_S *pstVgsAddOsd;
    10. VGS_DRAW_LINE_S *pstVgsDrawLine;
    11. VGS_TASK_ATTR_S stTaskAttr;
    12. }VGS_JOB_Task_S;
    1. typedef struct _dsVGS_JOB_S {
    2. TSM_BOOL bValid;
    3. VGS_HANDLE hHandle;
    4. DS_S32 s32TaskTotalNum;//VGS_JOB_TASK_MAX_NUMBER 200,task total sum.
    5. DS_U8 u8TaskArrayValidNum;//pstJobTask cur use pcs
    6. DS_U8 u8TaskArrayTotalNum;//pstJobTask total pcs
    7. VGS_JOB_Task_S **pstJobTask;
    8. }VGS_JOB_S;

     对GPU来说,每一个操作都是一个task,我们用一个vgs job task来记录,enOpType记录了当前这个task是什么类型,而Job结构体中是存放task的,每次task的数量是不一定,因此设计了一个二维指针,也就是双指针来存储。用户在申请一个job的时候,我们默认先个这个pstJobTask申请可以存储10组task的数据块,这个10组可以自定义修改的;

    1. pstJobNode->pstJobTask = malloc(sizeof(VGS_JOB_Task_S *) * 10);
    2. if(DS_NULL == pstJobNode->pstJobTask){
    3. VGS_PRT("pstJobTask malloc fail!\n");
    4. return DS_ERR_VGS_NOBUF;
    5. }
    6. memset(pstJobNode->pstJobTask, 0, sizeof(sizeof(VGS_JOB_Task_S *) * 10));

         因为每个job task占的数量也不大,一次分配10个,多数情况下是够用的了,所以免得申请小了又要频繁去修改这个内存,牺牲一点空间换效率;当这个10个task还不够存的情况下,我们就需要修改这个内存快,可以用realloc,

    1. if(pstJobNode->u8TaskArrayValidNum == pstJobNode->u8TaskArrayTotalNum
    2. && pstJobNode->u8TaskArrayValidNum > 0){
    3. _VGS_PRT("task is too full!Need remalloc\n");
    4. pstJobNode->pstJobTask = realloc(pstJobNode->pstJobTask,
    5. sizeof(VGS_JOB_Task_S *)*(pstJobNode->u8TaskArrayValidNum + 5));
    6. if(TSM_NULL == pstJobNode->pstJobTask[pstJobNode->u8TaskArrayValidNum]){
    7. _VGS_PRT("task is too full!Need remalloc\n");
    8. return TSM_FALSE;
    9. }
    10. memset(pstJobNode->pstJobTask[pstJobNode->u8TaskArrayValidNum], 0, sizeof(sizeof(VGS_JOB_Task_S *) * 5));
    11. pstJobNode->u8TaskArrayTotalNum += 5;
    12. }

         每次添加任务的时候,检查一下存task的空间还够不够,不够了再增量重申请一下,这样就能保证用户需要就加多少,既能避免一次性申请过多内存实际上浪费了的情况,又考虑了频繁malloc和realloc内存快的系统执行效率。在代价不大的情况下,空间和效率兼顾。

  • 相关阅读:
    yolo格式转labelme格式并验证
    金九银十求职季,Java自动化面试题分享
    常见插件 tomcat插件
    简单理解事件冒泡和事件捕获
    【算法专题--链表】两两交换链表中的节点 -- 高频面试题(图文详解,小白一看就懂!!!)
    go调用阿里云接口查询ECS信息
    甘特图来啦,项目管理神器,模板直接用
    详解Git合并(Merge)错误如何回退。(包括Reset, Revert和页面回滚三种,并说明其优缺点)
    微信小程序如何循环控制一行显示几个
    B. 看比赛 The 10th Jimei University Programming Contest
  • 原文地址:https://blog.csdn.net/sundesheng125/article/details/125460114