首页 > 系统相关 >一种尽可能减小内存占用的数据结构设计方法

一种尽可能减小内存占用的数据结构设计方法

时间:2024-07-06 12:11:57浏览次数:1  
标签:std false 占用 back vector bool 内存 push 数据结构

  

      背景:以三维点为例,随着采集设备的日新月异,三维点的属性信息也越来越多(例如颜色、强度、回波信息、gps时间等);导致点云数据在处理时加载到计算机中所需要的内存空间也越来越大,但是有些数据往往只有x、y、z三个坐标值,则不需要为其开辟多余的内存空间,那一套统一的数据结构怎样才做到灵活兼容呢(加载数据时尽可能少的占用内存空间),vcg的底层数据结构则提供了一种方案,其可以根据需要进行内存的申请。下面的代码是来自于vcg数据结构里的一段代码。

      

template <class VALUE_TYPE>
class vector_ocf: public std::vector<VALUE_TYPE> {
    typedef std::vector<VALUE_TYPE> BaseType;
    typedef typename vector_ocf<VALUE_TYPE>::iterator ThisTypeIterator;

public:
  vector_ocf():std::vector<VALUE_TYPE>()
  {
    ColorEnabled = false;
    CurvatureEnabled = false;
    CurvatureDirEnabled = false;
    MarkEnabled = false;
    NormalEnabled = false;
    QualityEnabled = false;
    RadiusEnabled = false;
    TexCoordEnabled = false;
    VFAdjacencyEnabled = false;
  }

////////////////////////////////////////
// All the standard methods of std::vector that can change the reallocation are
// redefined in order to manage the additional data.
  void push_back(const VALUE_TYPE & v)
    {
        BaseType::push_back(v);
        BaseType::back()._ovp = this;
        if (ColorEnabled)         CV.push_back(vcg::Color4b(vcg::Color4b::White));
        if (QualityEnabled)       QV.push_back(0);
        if (MarkEnabled)          MV.push_back(0);
        if (NormalEnabled)        NV.push_back(typename VALUE_TYPE::NormalType());
        if (TexCoordEnabled)      TV.push_back(typename VALUE_TYPE::TexCoordType());
        if (VFAdjacencyEnabled)   AV.push_back(VFAdjType());
        if (CurvatureEnabled)     CuV.push_back(typename VALUE_TYPE::CurvatureType());
        if (CurvatureDirEnabled)  CuDV.push_back(typename VALUE_TYPE::CurvatureDirType());
        if (RadiusEnabled)        RadiusV.push_back(typename VALUE_TYPE::RadiusType());
    }

    void pop_back();

    void resize(size_t _size)
    {
        const size_t oldsize = BaseType::size();
            BaseType::resize(_size);
        if(oldsize<_size){
            ThisTypeIterator firstnew = BaseType::begin();
            advance(firstnew,oldsize);
            _updateOVP(firstnew,(*this).end());
        }
        if (ColorEnabled)         CV.resize(_size);
        if (QualityEnabled)       QV.resize(_size,0);
        if (MarkEnabled)          MV.resize(_size);
        if (NormalEnabled)        NV.resize(_size);
        if (TexCoordEnabled)      TV.resize(_size);
        if (VFAdjacencyEnabled)   AV.resize(_size,VFAdjType::Zero());
        if (CurvatureEnabled)     CuV.resize(_size);
        if (CurvatureDirEnabled)  CuDV.resize(_size);
        if (RadiusEnabled)        RadiusV.resize(_size);
    }

    void reserve(size_t _size)
    {
        BaseType::reserve(_size);
        if (ColorEnabled)        CV.reserve(_size);
        if (QualityEnabled)      QV.reserve(_size);
        if (MarkEnabled)         MV.reserve(_size);
        if (NormalEnabled)       NV.reserve(_size);
        if (TexCoordEnabled)     TV.reserve(_size);
        if (VFAdjacencyEnabled)  AV.reserve(_size);
        if (CurvatureEnabled)    CuV.reserve(_size);
        if (CurvatureDirEnabled) CuDV.reserve(_size);
        if (RadiusEnabled)       RadiusV.reserve(_size);
    }

    void _updateOVP(ThisTypeIterator lbegin, ThisTypeIterator lend)
    {
        ThisTypeIterator vi;
        for(vi=lbegin;vi!=lend;++vi)
                (*vi)._ovp=this;
    }

////////////////////////////////////////
// Enabling Eunctions

bool IsQualityEnabled() const {return QualityEnabled;}
void EnableQuality() {
    assert(VALUE_TYPE::HasQualityOcf());
    QualityEnabled=true;
    QV.resize((*this).size(),0);
}
void DisableQuality() {
    assert(VALUE_TYPE::HasQualityOcf());
    QualityEnabled=false;
    QV.clear();
}

bool IsColorEnabled() const {return ColorEnabled;}
void EnableColor() {
    assert(VALUE_TYPE::HasColorOcf());
    ColorEnabled=true;
    CV.resize((*this).size());
}
void DisableColor() {
    assert(VALUE_TYPE::HasColorOcf());
    ColorEnabled=false;
    CV.clear();
}

bool IsMarkEnabled() const {return MarkEnabled;}
void EnableMark() {
    assert(VALUE_TYPE::HasMarkOcf());
    MarkEnabled=true;
    MV.resize((*this).size(),0);
}
void DisableMark() {
    assert(VALUE_TYPE::HasMarkOcf());
    MarkEnabled=false;
    MV.clear();
}

bool IsNormalEnabled() const {return NormalEnabled;}
void EnableNormal() {
    assert(VALUE_TYPE::HasNormalOcf());
    NormalEnabled=true;
    NV.resize((*this).size());
}
void DisableNormal() {
    assert(VALUE_TYPE::HasNormalOcf());
    NormalEnabled=false;
    NV.clear();
}

bool IsVFAdjacencyEnabled() const {return VFAdjacencyEnabled;}
void EnableVFAdjacency() {
    assert(VALUE_TYPE::HasVFAdjacencyOcf());
    VFAdjacencyEnabled=true;
    AV.resize((*this).size(),VFAdjType::Zero());
}
void DisableVFAdjacency() {
    assert(VALUE_TYPE::HasVFAdjacencyOcf());
    VFAdjacencyEnabled=false;
    AV.clear();
}

bool IsCurvatureEnabled() const {return CurvatureEnabled;}
void EnableCurvature() {
    assert(VALUE_TYPE::HasCurvatureOcf());
    CurvatureEnabled=true;
    CuV.resize((*this).size());
}
void DisableCurvature() {
    assert(VALUE_TYPE::HasCurvatureOcf());
    CurvatureEnabled=false;
    CuV.clear();
}

bool IsCurvatureDirEnabled() const {return CurvatureDirEnabled;}
void EnableCurvatureDir() {
    assert(VALUE_TYPE::HasCurvatureDirOcf());
    CurvatureDirEnabled=true;
    CuDV.resize((*this).size());
}
void DisableCurvatureDir() {
    assert(VALUE_TYPE::HasCurvatureDirOcf());
    CurvatureDirEnabled=false;
    CuDV.clear();
}

bool IsRadiusEnabled() const {return RadiusEnabled;}
void EnableRadius() {
    assert(VALUE_TYPE::HasRadiusOcf());
    RadiusEnabled=true;
    RadiusV.resize((*this).size());
}
void DisableRadius() {
    assert(VALUE_TYPE::HasRadiusOcf());
    RadiusEnabled=false;
    RadiusV.clear();
}


bool IsTexCoordEnabled() const {return TexCoordEnabled;}
void EnableTexCoord() {
    assert(VALUE_TYPE::HasTexCoordOcf());
    TexCoordEnabled=true;
    TV.resize((*this).size());
}
void DisableTexCoord() {
    assert(VALUE_TYPE::HasTexCoordOcf());
    TexCoordEnabled=false;
    TV.clear();
}

struct VFAdjType {
    VFAdjType():_fp(0),_zp(-1) {}
  VFAdjType(typename VALUE_TYPE::FacePointer fp, int zp):_fp(fp),_zp(zp){}
    typename VALUE_TYPE::FacePointer _fp ;
    int _zp ;
    static VFAdjType Zero() { return VFAdjType(0,-1); }
    bool IsNull() const { return (_zp ==-1); }
    };

public:
  std::vector<typename VALUE_TYPE::ColorType> CV;
  std::vector<typename VALUE_TYPE::CurvatureType> CuV;
  std::vector<typename VALUE_TYPE::CurvatureDirType> CuDV;
  std::vector<int> MV;
  std::vector<typename VALUE_TYPE::NormalType> NV;
  std::vector<typename VALUE_TYPE::QualityType> QV;
  std::vector<typename VALUE_TYPE::RadiusType> RadiusV;
  std::vector<typename VALUE_TYPE::TexCoordType> TV;
  std::vector<struct VFAdjType> AV;

  bool ColorEnabled;
  bool CurvatureEnabled;
  bool CurvatureDirEnabled;
  bool MarkEnabled;
  bool NormalEnabled;
  bool QualityEnabled;
  bool RadiusEnabled;
  bool TexCoordEnabled;
  bool VFAdjacencyEnabled;
};

 

      下面这个函数很好的诠释了内存申请的过程。如果对该属性不进行内存空间的申请,后期该属性相关的数据则无法访问或者越界导致程序崩溃。

void EnableNormal() 
{ assert(VALUE_TYPE::HasNormalOcf()); NormalEnabled=true; NV.resize((*this).size()); }

 所以在初始化点云对象之前会根据点云数据里已有的属性进行相应字段的内存空间的开辟;

例如:

PointCloud pc;//只是个示例

pc.EnableNormal();

pc.CurvatureEnabled();

...

     所以在访问该字段的数据时,也应该要加以判断,不然就会出现数组越界导致程序崩溃的问题出现。

譬如访问Curvature属性时,则需要根据CurvatureEnabled变量进行判断该属性是否存在数据。

      此外,由于大地坐标的有效数字超过了7位,所以也只有double类型才能适配,众所周知double占8个字节,float占4个字节,一倍的差距对于大数据量的点云加载到内存中所引起的内存占用过高的问题是很明显的,所以建议设置一个中心坐标,然后将数据转成局部坐标(小坐标),这样可以较大程度较少点云数据加载到程序中所占用的内存。

    通过以上两个手段来设计内存数据结构,能较大程度减少数据量过大内存空间不够的问题(多则能降低一半以上,少则也能降低1/3)。

    当然一些字段也可以一个int类型,例如回波次数、回波序号采用二进制的手段共有一个int似乎也是可行的。

    

标签:std,false,占用,back,vector,bool,内存,push,数据结构
From: https://www.cnblogs.com/z-web-2017/p/18284210

相关文章

  • pwn的linux基础(计算机内部数据结构存储形式)
    linux基础保护层级:分为四个ring0-ring3一般来说就两个,0和30为内核3为用户 权限:用户分为多个组文件和目录等等的权限一般都是三个,即可读可写可执行。读:R,写:W,执行:X赋予一个可执行文件执行权限就是chmod+xfilename虚拟内存和物理内存:物理内存很直白,就是内存......
  • 内存管理-15-slab、slob和slub分配器-初探
    一、slab简介1.简介首先,“slab”已成为一个通用名称,指的是使用对象缓存的内存分配策略,可实现内核对象的高效分配和释放。它最初由Sun工程师JeffBonwick记录下来,并在Solaris2.4内核中实现。Linux目前为其“slab”分配器提供了三种选择:Slab是最初的分配器,基于Bonwic......
  • 内存管理-16-kmalloc机制实现-初探
    一、概述slab的接口比较麻烦,kmalloc接口使用简便,其底层是基于slab缓存机制实现的,主要也是从slab缓存中拿内存对象。//include/linux/slab.hstatic__always_inlinevoid*kmalloc(size_tsize,gfp_tflags)voidkfree(constvoid*x)GFP_USER:由user发起的内存申请,可以......
  • 引用个数为什么会影响内存泄漏 c++例子
    在C++中,内存泄漏通常与手动管理内存有关,而不是直接由引用计数引起,因为C++标准库本身并不提供自动的引用计数功能。但是,我们可以通过一个例子来间接说明引用(或指针)管理不当如何导致内存泄漏,尤其是当涉及复杂对象结构和所有权关系时,这种管理不当往往体现在循环引用上。基本概念......
  • 端口占用问题解决方案(Windows)
    端口占用问题解决方案(Windows)在开发和运维过程中,我们经常会遇到端口被占用的情况。这可能导致服务器启动失败或者其他服务无法正常运行。本文将介绍如何使用命令行工具来查询和解决端口占用问题。一、查询当前所有端口使用情况可以使用netstat-ano命令来查看当前所有......
  • 内存映射
    mmap内存映射函数(显示图片的新方法)----也是Linux系统IO中的函数之一基本概念系统IO函数的共同点:就是他们的形参中一定有一个是文件描述符(除open)。内存映射的意思:拆内存:普通运存,显存(集显和独显),是一块内存空间,存放显示画面的像素点。映射:两个集合中的元素,都具有......
  • python数据结构(树和二叉树)
    树非线性结构一对多根结点(无前驱)多个叶子结点(无后继)其他数据元素(一个前驱,多个后驱)树与二叉树转换树与二叉树均可用二叉链表作为存储结构,则以二叉链表为媒介可导出树之间的一个对应关系-----即给定一颗树,可以找到唯一一颗二叉树与之对应。把树转化为二叉树步骤一:加线......
  • 内存缓存选型
    背景tcp网关出现了内存泄漏的现象,经排查后发现是一个java原生内存缓存导致的。Map<String,String>belongCache=newConcurrentHashMap<>();该内存缓存作为兜底缓存使用,主要逻辑是读取redis用户身份信息后,有则更新到内存缓存,没有则从内存缓存中获取缓存数据。该内存缓存直......
  • Redis数据结构-字典的实现
    字典,又称符号表(symboltable)、关联数组(associativearray)或者映射(map),是一种用于保存键值对(key-valuepair)的抽象数据结构。在字典中,一个键(key)可以和一个值(value)进行关联(或者说将键映射为值),这些关联的键和值就被称为键值对。字典中的每个键都是独一无二的,程序可以在字典......
  • 从零开始学数据结构系列之第四章《 广度优先遍历BFS》
    文章目录广度优先遍历(BFS)概念广度优先遍历算法步骤总代码往期回顾广度优先遍历(BFS)概念​  广度优先遍历(BreadthFirstSearch),又称为广度优先搜索,简称BFS。​  如果说图的深度优先遍历类似树的前序遍历,那么图的广度优先遍历就类似于树的层序遍历了。​ ......