LMDB使用说明_知海无涯学无止境的博客-CSDN博客_lmdb++


本站和网页 https://blog.csdn.net/jyl1999xxxx/article/details/53942824 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

LMDB使用说明_知海无涯学无止境的博客-CSDN博客_lmdb++
LMDB使用说明
知海无涯学无止境
于 2016-12-30 14:39:30 发布
29874
收藏
10
http://rayz0620.github.io/2015/05/25/lmdb_in_caffe/
官方的extract_feature.bin很好用,但是输出的特征是放在LMDB里的。以前嫌LMDB麻烦,一直都图方便直接用ImageDataLayer来读原始图像。这次绕不过去了,就顺便研究了一下Caffe对LMDB的使用,一些心得写下来和大家分享一下。提取特征的内容下一篇再写。
Caffe中DataLayer默认的数据格式是LMDB。许多example中提供的输入数据是LMDB格式。使用extract_features.bin提取特征时支持的输出格式之一也是LMDB。LMDB在Caffe的IO功能中有相当重要的地位。因此,搞明白如何存取Caffe的LMDB数据,对于我们使用Caffe是很有帮助的。
LMDB
Caffe使用LMDB来存放训练/测试用的数据集,以及使用网络提取出的feature(为了方便,以下还是统称数据集)。数据集的结构很简单,就是大量的矩阵/向量数据平铺开来。数据之间没有什么关联,数据内没有复杂的对象结构,就是向量和矩阵。既然数据并不复杂,Caffe就选择了LMDB这个简单的数据库来存放数据。
LMDB的全称是Lightning Memory-Mapped Database,闪电般的内存映射数据库。它文件结构简单,一个文件夹,里面一个数据文件,一个锁文件。数据随意复制,随意传输。它的访问简单,不需要运行单独的数据库管理进程,只要在访问数据的代码里引用LMDB库,访问时给文件路径即可。
图像数据集归根究底从图像文件而来。既然有ImageDataLayer可以直接读取图像文件,为什么还要用数据库来放数据集,增加读写的麻烦呢?我认为,Caffe引入数据库存放数据集,是为了减少IO开销。读取大量小文件的开销是非常大的,尤其是在机械硬盘上。LMDB的整个数据库放在一个文件里,避免了文件系统寻址的开销。LMDB使用内存映射的方式访问文件,使得文件内寻址的开销非常小,使用指针运算就能实现。数据库单文件还能减少数据集复制/传输过程的开销。一个几万,几十万文件的数据集,不管是直接复制,还是打包再解包,过程都无比漫长而痛苦。LMDB数据库只有一个文件,你的介质有多块,就能复制多快,不会因为文件多而慢如蜗牛。
Caffe中的LMDB数据
接下来要介绍Caffe是如何使用LMDB存放数据的。 Caffe中的LMDB数据大约有两类:一类是输入DataLayer的训练/测试数据集;另一类则是extract_feature输出的特征数据。
Datum数据结构
首先需要注意的是,Caffe并不是把向量和矩阵直接放进数据库的,而是将数据通过caffe.proto里定义的一个datum类来封装。数据库里放的是一个个的datum序列化成的字符串。Datum的定义摘录如下:
10
11
12
message Datum {
optional int32 channels = 1;
optional int32 height = 2;
optional int32 width = 3;
// the actual image data, in bytes
optional bytes data = 4;
optional int32 label = 5;
// Optionally, the datum could also hold float data.
repeated float float_data = 6;
// If true data contains an encoded image that need to be decoded
optional bool encoded = 7 [default = false];
一个Datum有三个维度,channels, height,和width,可以看做是少了num维度的Blob。存放数据的地方有两个:byte_data和float_data,分别存放整数型和浮点型数据。图像数据一般是整形,放在byte_data里,特征向量一般是浮点型,放在float_data里。label存放数据的类别标签,是整数型。encoded标识数据是否需要被解码(里面有可能放的是JPEG或者PNG之类经过编码的数据)。
Datum这个数据结构将数据和标签封装在一起,兼容整形和浮点型数据。经过Protobuf编译后,可以在Python和C++中都提供高效的访问。同时Protubuf还为它提供了序列化与反序列化的功能。存放进LMDB的就是Datum序列化生成的字符串。
Caffe中读写LMDB的代码
要想知道Caffe是如何使用LMDB的,最好的方法当然是去看Caffe的代码。Caffe中关于LMDB的代码有三类:生成数据集、读取数据集、生成特征向量。接下来就分别针对三者进行分析。
生成数据集
生成数据集的代码在examples,随数据集提供,比如MNIST。
首先,创建访问LMDB所需的一些变量:
MDB_env *mdb_env;
MDB_dbi mdb_dbi;
MDB_val mdb_key, mdb_data;
MDB_txn *mdb_txn;
...
mdb_env是整个数据库环境的句柄,mdb_dbi是环境中一个数据库的句柄,mdb_key和mdb_data用来存放向数据库中输入数据的“值”。mdb_txn是数据库事物操作的句柄,”txn”是”transaction”的缩写。
然后,创建数据库环境,创建并打开数据库:
10
11
12
13
14
15
16
if (db_backend == "lmdb") { // lmdb
LOG(INFO) << "Opening lmdb " << db_path;
CHECK_EQ(mkdir(db_path, 0744), 0)
<< "mkdir " << db_path << "failed";
CHECK_EQ(mdb_env_create(&mdb_env), MDB_SUCCESS) << "mdb_env_create failed";
CHECK_EQ(mdb_env_set_mapsize(mdb_env, 1099511627776), MDB_SUCCESS) // 1TB
<< "mdb_env_set_mapsize failed";
CHECK_EQ(mdb_env_open(mdb_env, db_path, 0, 0664), MDB_SUCCESS)
<< "mdb_env_open failed";
CHECK_EQ(mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn), MDB_SUCCESS)
<< "mdb_txn_begin failed";
CHECK_EQ(mdb_open(mdb_txn, NULL, 0, &mdb_dbi), MDB_SUCCESS)
<< "mdb_open failed. Does the lmdb already exist? ";
} else {
LOG(FATAL) << "Unknown db backend " << db_backend;
第3行代码为数据库创建文件夹,如果文件夹已经存在,程序会报错退出。也就是说,程序不会覆盖已有的数据库。已有的数据库如果不要了,需要手动删除。第13行处创建并打开了一个数据库。需要注意的是,LMDB的一个环境中是可以有多个数据库的,数据库之间以名字区分。mdb_open()的第二个参数实际上就是数据库的名称(char *)。当一个环境中只有一个数据库的时候,这个参数可以给NULL。
最后,为每一个图像创建Datum对象,向对象内写入数据,然后将其序列化成字符串,将字符串放入数据库中:
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Datum datum;
datum.set_channels(1);
datum.set_height(rows);
datum.set_width(cols);
for (int item_id = 0; item_id < num_items; ++item_id) {
image_file.read(pixels, rows * cols);
label_file.read(&label, 1);
datum.set_data(pixels, rows*cols);
datum.set_label(label);
snprintf(key_cstr, kMaxKeyLength, "%08d", item_id);
datum.SerializeToString(&value);
string keystr(key_cstr);
// Put in db
if (db_backend == "lmdb") { // lmdb
mdb_data.mv_size = value.size();
mdb_data.mv_data = reinterpret_cast<void*>(&value[0]);
mdb_key.mv_size = keystr.size();
mdb_key.mv_data = reinterpret_cast<void*>(&keystr[0]);
CHECK_EQ(mdb_put(mdb_txn, mdb_dbi, &mdb_key, &mdb_data, 0), MDB_SUCCESS)
<< "mdb_put failed";
} else {
LOG(FATAL) << "Unknown db backend " << db_backend;
if (++count % 1000 == 0) {
// Commit txn
if (db_backend == "lmdb") { // lmdb
CHECK_EQ(mdb_txn_commit(mdb_txn), MDB_SUCCESS)
<< "mdb_txn_commit failed";
CHECK_EQ(mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn), MDB_SUCCESS)
<< "mdb_txn_begin failed";
} else {
LOG(FATAL) << "Unknown db backend " << db_backend;
放入数据的Key是图像的编号,前面补0至8位。需要注意的是18至21行,MDB_val类型的mdb_data和mdb_key中存放的是数据来源的指针,以及数据的长度。第20行的mdb_put()函数将数据存入数据库。每隔1000个图像commit一次数据库。只有commit之后,数据才真正写入磁盘。
读取数据集
Caffe中读取LMDB数据集的代码是DataLayer,用在网络的最下层,提供数据。DataLayer采用顺序遍历的方式读取数据,不支持打乱数据顺序,只能随机跳过前若干个数据。
首先,在DataLayer的DataLayerSetUp方法中,打开数据库,并获取迭代器cursor_:
db_.reset(db::GetDB(this->layer_param_.data_param().backend()));
db_->Open(this->layer_param_.data_param().source(), db::READ);
cursor_.reset(db_->NewCursor());
然后,在每一次的数据预取时,InternalThreadEntry()方法中,从数据库中读取字符串,反序列化为Datum对象,再从Datum对象中取出数据:
Datum datum;
datum.ParseFromString(cursor_->value());
其中,cursor_->value()获取序列化后的字符串。datum.ParseFromString()方法对字符串进行反序列化。
最后,要将cursor_向前推进:
cursor_->Next();
if (!cursor_->valid()) {
DLOG(INFO) << "Restarting data prefetching from start."
cursor_->SeekToFirst();
如果cursor->valid()返回false,说明数据库已经遍历到头,这时需要将cursor_重置回数据库开头。
不支持样本随机排序应该是DataLayer的致命弱点。如果数据库的key能够统一,其实可以通过对key随机枚举的方式实现。
知海无涯学无止境
关注
关注
点赞
10
收藏
评论
LMDB使用说明
http://rayz0620.github.io/2015/05/25/lmdb_in_caffe/官方的extract_feature.bin很好用,但是输出的特征是放在LMDB里的。以前嫌LMDB麻烦,一直都图方便直接用ImageDataLayer来读原始图像。这次绕不过去了,就顺便研究了一下Caffe对LMDB的使用,一些心得写下来和大家分享一下。提取特征的内容下一篇再写。
复制链接
扫一扫
lmdb++:LMDB嵌入式B +树数据库库的C ++ 11包装器。-开源
04-25
这是LMDB嵌入式数据库库的全面C ++包装器,提供了经过错误检查的过程接口和具有RAII语义的面向对象的资源接口。 •设计成完全独立的单一设备可以放入项目的头文件。 •使用一致的命名实现从C到C ++的直接映射。 •提供过程接口和面向对象的RAII接口。 •通过将错误代码转换为C ++异常来简化错误处理。 •仔细区分逻辑错误,运行时错误和致命错误。 •异常字符串包括失败的LMDB函数的名称。 •与其他人一起玩:所有符号都放置在lmdb命名空间中。 •100%免费且不受限制的公共领域软件,可在任何情况下以任何目的使用。
Py之lmdb:lmdb的简介、安装、使用方法之详细攻略
热门推荐
心比天高,仗剑走天涯,保持热爱,奔赴向梦想!低调,谦虚,自律,反思,成长,还算是比较正能量的博主,公益免费传播……
05-17
2万+
Py之lmdb:lmdb的简介、安装、使用方法之详细攻略
目录
lmdb的简介
lmdb的安装
lmdb的使用方法
lmdb的简介
LMDB,即Lightning Memory-Mapped Database Manager 闪电内存映射数据库管理器。是一个基于btree的数据库管理库,松散地建模于BerkeleyDB API,但...
评论 3
您还未登录,请先
登录
后发表或查看评论
一款非常优秀的内存数据库——lmdb
HuaShao
09-18
5201
lmdb是一款开源的高效快速的内存映射数据库,C语言编写,基于B+树索引,支持MVCC事务处理,是一个嵌入到进程的数据库,不需要单独的数据库进程,在代码中使用lmdb的接口即可方便地实现读写lmdb数据库。
github:https://github.com/LMDB/lmdb.git
下载并编译、安装
git clone https://github.com/LMDB/lmdb.git
cd lmdb/libraries/liblmdb
make
sudo make install
示例代.
LMDB使用说明_ldd教程
最新发布
qq_43934844的博客
11-11
51
LMDB使用说明_ldd教程
【数据库】Py之lmdb:lmdb的简介、安装、使用方法之详细攻略
devil_son1234的博客
01-21
1648
目录
lmdb的简介
lmdb的安装
lmdb的使用方法
lmdb的简介
LMDB,即Lightning Memory-Mapped Database Manager 闪电内存映射数据库管理器。是一个基于btree的数据库管理库,松散地建模于BerkeleyDB API,但是进行了很多简化。整个数据库在内存映射中公开,所有数据获取都直接从映射的内存返回数据,因此在数据获取期间不会出现malloc或memcpy。因此,这个库非常简单,因为它本身不需要页面缓存层,而且它的性能和内存效率都非..
lmdb性能测试——代码及结果
HuaShao
09-18
886
#include <iostream>
#include <string>
#include <chrono>
#include "lmdb.h"
using namespace std;
int main(int argc, char* argv[]){
int res;
MDB_env *env;
MDB_dbi dbi;
MDB_val key, data;
MDB_txn *txn;
//init lm.
轻量级内存映射数据库LMDB(快如闪电)
程序猿
08-21
3783
LMDB为一个轻量级的,内存映射数据库,存储结构类似于redis,采用key-value方式存储,数据结构为字节数组
LMDB能够提供:
1. 事务(完整的ACID语义)
2. 有序键(支持非常快速的基于指针的迭代)
3. 内存映射文件(支持最佳操作系统内存管理)
4. 零拷贝设计(没有序列化或内存拷贝开销)
5. 读写没有阻塞
6. 无配置(无序...
LINUX使用C调用LMDB的方法
柳鲲鹏
09-14
1243
下载代码
https://github.com/LMDB/lmdb
解压
make && sudo make install
注意需要的是lmdb.h还是lmdb++.h。
配置
检查.bashrc的,如果没有/usr/local/lib,要加上。
简单测试
先在当前目录先:
mkdir testdb
再执行:
./mtest
代码如下
#include...
LMDB:轻量级内存映射数据库-----入门使用1
本博客纯属个人学习记载,不对外负责,若有错误,请批评指正
05-27
3616
前言
在前文LMDB简介的基础上,本文介绍LMDB数据库的基本用法,包括环境environment创建、数据存储put、数据读取get等;
源码
ULONG cvtest_Test4_Lmdb()
INT iRet;
MDB_txn *pstTxn = NULL;
MDB_dbi stDbi;
UINT uiKey = 1;
...
LMDB笔记
欢迎光临啊噗不是阿婆主的酒馆
07-19
2441
作为一个计算机底层小白,在了解一个知识点的时候时常需要恶补很多基础知识。
本文记录在了解LMDB过程中接触的知识点。
LMDB基本架构
一个比较官方的解释:lmdb的基本做法是使用mmap文件映射,不管这个文件存储实在内存上还是在持久存储上。lmdb的所有读取操作都是通过mmap将要访问的文件只读的映射到虚拟内存中,直接访问相应的地址.因为使用了read-only的mmap,同样避免了程序错误将存...
【分享】Java一个键(key)对多个值(value)存储
清风唱诗人的博客
09-02
3513
1.概述
在本教程中,我们将探讨用于处理具有重复键的Map的可用选项,或者换言之,允许为单个键存储多个值的Map。
2.标准Map
Java有几个接口Map的实现,每个都有自己的特殊性。
但是,现有的Java核心Map实现都不允许Map处理单个键的多个值。
我们可以看到,如果我们尝试为同一个键插入两个值,则将存储第二个值,而第一个值将被删除。
它也将被返回(通过*put(K键,V值)*方法的每个正确实现):
Map<String, String> map = new Hash..
Python中使用LMDB
MA201506的博客
03-06
218
在python中使用lmdb
linux中,可以使用指令pip install lmdb安装lmdb包。
生成一个空的lmdb数据库文件
# -*- coding: utf-8 -*-
import lmdb
# 如果train文件夹下没有data.mbd或lock.mdb文件,则会生成一个空的,如果有,不会覆盖
# map_size定义最大储存容量,单位是kb,以下定义1TB容量
en...
LMDB(一) -- 简介
12-15
3951
http://www.jianshu.com/p/yzFf8j
lmdb简介
lmdb是openLDAP项目开发的嵌入式(作为一个库嵌入到宿主程序)存储引擎。其主要特性有:
基于文件映射IO(mmap)基于B+树的key-value接口基于MVCC(Multi Version Concurrent Control)的事务处理类bdb(berkeley db)的api
文件格式之lmdb
Touch_Dream的博客
05-31
1870
使用caffe对数据进行处理时,需要将图片转化为lmdb格式的。 求助百度百科,无词条,求助wikipedia,成功,地址. lmdb 是Lightning Memory-Mapped Database的缩写。 LMDB示例文件为 它包含一个数据文件和一个锁文件。python 操作参考教程1,教程2和教程3 python module 为lmdb 直接通过pip进行安装pip install lm...
Caffe中LMDB接口实现多标签数据准备及训练
Hyman's Blog
06-30
1万+
Caffe中使用LMDB实现多标签数据的准备
使用caffe制作自己的lmdb数据集
zhaoyoulin2016的博客
07-25
4231
新鸟最近在一家半导体公司实习,接触到的项目都是基于 caffe框架的深度学习方面的知识,前期对tensorflow比较熟,但是到了公司没办法啊!!!不会怎么办,只能硬着头皮上啊!!!!中途碰壁不少,写这篇博客只是想以后方便查阅资料,另外一方面是给同样在深度学习里面摸爬滚打的朋友一个参考吧!!!!
公司提供的数据都是工程师切分好的数据集,但是图像的大小有大有小,不能直接拿过来用在神...
多进程加速LMDB文件写入及使用LMDB时遇到的问题
Princes1997的博客
04-04
1259
项目场景:
LMDB数据库可以同时由多个进程打开,使用内存映射的方式访问文件使得文件内寻址的开销非常小,能有效减少数据集复制/传输过程的开销,具有极高的数据存取速度
最近尝试将数据集写入LMDB以提高模型训练速度
使用以下代码将数据集多进程加速写入LMDB
def write_lmdb(train_image_list):
env = lmdb.open('../dataset/train_', 13610000000)
cache = {}
for idx, (image, lab
PyTorch使用LMDB数据库加速文件读取
画心
11-22
8113
PyTorch使用LMDB数据库加速文件读取
文章目录PyTorch使用LMDB数据库加速文件读取背景介绍具体操作LMDB主要类`lmdb.Environment``lmdb.Transaction``Imdb.Cursor`操作流程创建图像数据集配合DataLoader参考链接
原始文档:https://www.yuque.com/lart/ugkv9f/hbnym1
对于数据库的了解较少,文...
生成caffe所用的lmdb数据
jancis的博客
10-30
232
本文只介绍在caffe框架下生成lmdb格式的数据,因为在caffe框架下训练和测试都只能用lmdb格式的数据:
准备:
1、ubuntu 18.04
2、新建data文件夹,内含train和test两个文件夹
3、train文件夹和test文件夹里面分别含img和xml两个文件夹,里面分别是原图像(.jpg格式)和标签(.xml格式,用LabelImage标注工具生成)
4、在trai...
“相关推荐”对你有帮助么?
非常没帮助
没帮助
一般
有帮助
非常有帮助
提交
©️2022 CSDN
皮肤主题:大白
设计师:CSDN官方博客
返回首页
知海无涯学无止境
CSDN认证博客专家
CSDN认证企业博客
码龄10年
暂无认证
27
原创
8万+
周排名
3945
总排名
66万+
访问
等级
5545
积分
56
粉丝
93
获赞
54
评论
235
收藏
私信
关注
热门文章
Ubuntu下查看显卡型号及NVIDIA驱动版本
139637
LMDB使用说明
29872
Python import以及os模块
24577
spyder 护眼背景
23899
MATLAB读取文件夹及其所有子文件夹内的图像
14233
分类专栏
视频编解码
4篇
最新评论
Precision-Recall Curve
???boom:
木有图呀
K-means与高斯混合模型
deardeerfighting:
您好,我想请问一下这句话“先用 K-means (已经重复并取最优值了)得到一个粗略的结果,然后将其作为初值(只要将 K-means 所得的 centroids 传入 gmm 函数即可),再用 GMM 进行细致迭代” 能展开具体说说吗
error: ‘CUDNN_CONVOLUTION_FWD_ALGO_WINOGRAD’ was not declared in this scope
miehmg:
其实只是cudnn8把版本头文件分离了,所以旧的cmakefile没找到cudnn的版本声明。改一下可能可以用,不过懒得试验了
程序无法启动ALL_BUILD 拒绝访问
Vigor0000:
感谢
error: ‘CUDNN_CONVOLUTION_FWD_ALGO_WINOGRAD’ was not declared in this scope
anlunson:
你好,请问你解决了这个问题吗?能分享一下方法吗?
您愿意向朋友推荐“博客详情页”吗?
强烈不推荐
不推荐
一般般
推荐
强烈推荐
提交
最新文章
sudo apt-get install 国内源
Ubuntu Anaconda 环境下删除 protobuf
CUDA Eclipse Nsight 不能打开工程 an error has occurred see the log file
2022年2篇
2021年1篇
2020年2篇
2019年22篇
2018年23篇
2017年57篇
2016年100篇
2015年5篇
目录
目录
分类专栏
视频编解码
4篇
目录
评论 3
被折叠的 条评论
为什么被折叠?
到【灌水乐园】发言
查看更多评论
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。
余额充值