【CXL】在gem5中跑一个实际的应用程序——Viper KV存储

news2024/11/25 15:47:51

有了CXL扩展内存,自然是要在DRAM+CXL扩展内存上跑跑实际的应用程序,看看和DRAM+传统磁盘有什么区别。
实际的应用程序其实就是一些工业界部署使用的,比如数据库、深度学习训练项目等等。本文主要找到一个KV存储Viper,搭建并进行简单的测试。
论文:Viper: An Efficient Hybrid PMem-DRAM Key-Value Store
github仓库:https://github.com/hpides/viper

文章目录

    • 一、KV存储简介
    • 二、Viper简介
      • 1. 设计方案
      • 2. 访问模式
    • 三、Viper安装
      • 1. 正常Ubuntu联网状态下的安装
      • 2. Ubuntu18.04 磁盘镜像中安装Viper
        • 安装cmake 3.26.3
        • 安装g++/gcc 9.4
        • 安装viper
    • 四、bug记录
      • 1. 有关gcc中libstdc++版本的问题
      • 2. 有关Illegal instruction的问题
    • 五、其他KVS

一、KV存储简介

KV存储就是键值对,和传统的关系型数据库不一样,没有很多SQL的范式约束,称作NOSQL,就是简单的键值对put、get操作,所以性能很高。
一般分两种KV存储(KVS):

  • 基于服务器的KVS
    • 常见:Redis、memchached
    • 特点:客户端/服务端API通过网络与应用程序通信、构建分布式存储系统
  • 嵌入式KVS
    • 常见:RocksDB、FASTER、LevelDB
    • 特点:轻量级;嵌入在应用程序中,一般通过引入头文件调用库函数进行访问;数据存储在本地

因为gem5全系统仿真下无法联网,所以使用基于服务器的KVS显然不现实;
另外,目前使用cxl设备的方式还是将其看做一个字符设备,使用mmap的方式来访问,所以需要创建文件来持久化保存数据的诸如LevelDB也不行。

万幸发现了Viper,一个很新的,非常轻量级的,代码可读性很好的,可以提供字符设备访问方式的KVS。

二、Viper简介

Viper是针对Pmem开发的一个KVS。

1. 设计方案

Viper的作者基于这样的出发点进行设计:对比Pmem、DRAM、SSD的读写性能,得到这样的结果:DRAM处理随机读写性能非常高,Pmem处理顺序写操作性能较高。

所以鼓励按顺序写入Pmem,尽可能将随机访问定向到DRAM,基于这样的特点,得到了一个设计方案:
Viper = DRAM中的易失性哈希索引 + PMem中的持久数据块
在这里插入图片描述
其实它的思想很简单,就是将键值对和键值对的索引分开存储。
DRAM适合随机访问,那么就让索引的哈希表存在DRAM里;
Pmem适合顺序写,那么就让实际的键值对按顺序存在Pmem里。

2. 访问模式

它支持三种访问模式:

  • DRAM+Pmem:Pmem上挂载DAX机制的文件系统;
  • DRAM+Pmem:配置Pmem为字符设备进行mmap访问;
  • DRAM+DRAM:配置仅仅运行在DRAM上,即哈希表与键值对都存在DRAM里。

三、Viper安装

1. 正常Ubuntu联网状态下的安装

其实Viper的readme说的比较清楚,也比较简单
依赖:

  • concurrentqueue 1.0.3的库,在CMakeLists.txt都链接好了
  • cmake version >= 3.14
  • c++17以上
  • 较高版本的g++/gcc,如g++9.4

正常的Ubuntu20.04一般都具备下面三个条件,第一个只要可以正常联网,就可以自动在github上下载。可以直接在Viper的目录下使用命令即可安装标准版:

mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .

自带有一个playground.cpp测试文件,要测试该文件可以在build目录下使用下面的命令:

cmake -DVIPER_BUILD_PLAYGROUND=ON ..
cmake --build . 

就可以看到build目录下有playground可执行文件了,直接./playground即可测试。

有关cmake编译选项,可以看Viper的CMakeLists.txt,里面有说明可以编译的选项:
option(VIPER_BUILD_PLAYGROUND “Set ON if playground should be built.” OFF)
option(VIPER_BUILD_BENCHMARKS “Set OM if benchmarks should be built.” OFF)


不过可能出现的问题就是,自己的电脑CPU不支持clwb指令集,该指令集主要是Intel的至强CPU支持的,一般的个人电脑可能不支持,可以通过修改CMakeLists.txt和Viper源码的方式避免使用clwb指令:

  1. 使用_mm_clflush替换_mm_clwb:在viper.hpp105行,将_mm_clwb换为_mm_clflush
    (这两个应该算是内嵌的汇编函数,两者功能上我浅显的理解应该差不多,但是前者在大部分的CPU都会支持。)

多亏了这个博客[非易失内存编程] 通过编译器内置函数 (Intrinsic Functions) 发射 CLFLUSH、CLFLUSHOPT、CLWB、NTSTORE、MFENCE、SFENCE 等指令,文中不但介绍了CLFLUSH、CLFLUSHOPT、CLWB等指令的区别,还介绍了使用内嵌汇编函数时遇到的一些问题,比如如何在编译时指定指令集扩展。
可以在这个文档 Intel Intrinsic Guide中查看Intel的一些汇编函数。

  1. 修改CMakeLists.txt:在CMakeLists.txt的21行和40行,将-mclwb修改为-msse2。重新进行cmake --build .即可。
    (_mm_clflush在sse2指令集中,cmake调用的是g++编译器,而-msse2选项是指告诉编译器当前使用了sse2这个扩展指令集。)

2. Ubuntu18.04 磁盘镜像中安装Viper

在磁盘镜像中有很多限制,一方面不能联网,另一方面其软件包如g++、cmake版本太低,所以无法按照上述正常编译使用Viper,需要安装高版本的g++和cmake

安装cmake 3.26.3

具体参考:Ubuntu18.04安装Cmake(最新最详细亲测)

  1. 在官网下载编译好的二进制包(这种方法简单一点,源码编译的方法容易出错。)在这里插入图片描述
    挂载磁盘文件参考:【CXL】使用memkind/vmem管理CXL扩展内存
    解压并复制到磁盘文件中
tar -zxvf cmake-3.26.3-linux-x86_64.tar.gz
sudo cp cmake-3.26.3-linux-x86_64 ~/gem5/full-system-image/disks/local_mnt/home/lib_source_code/ -r
  1. 使用sudo chroot ./命令进入磁盘文件之后,为cmake配置环境变量
    这里我的做法有点奇怪,不过貌似效果是一样的。
    正常按照参考博客的方法二添加软链接应该就可以使用了,如下:
ln -sf /home/lib_source_code/cmake-3.26.3-linux-x86_64/bin/* /usr/local/bin/

但是我不得行,只能使用下面的方法(有点简单粗暴,如果有更好的方法可以不用下面的办法):
我在/usr/local/bin//usr/local/share/目录下发现了旧版本的cmake文件,于是我选择将3.26的cmake文件进行对应替换,就是直接cp过去覆盖旧文件:

cp cmake-3.26.3-linux-x86_64/bin/ccmake /usr/local/bin/
cp cmake-3.26.3-linux-x86_64/bin/cmake /usr/local/bin/
cp cmake-3.26.3-linux-x86_64/bin/cmake-gui /usr/local/bin/
cp cmake-3.26.3-linux-x86_64/bin/cpack /usr/local/bin/
cp cmake-3.26.3-linux-x86_64/bin/ctest /usr/local/bin/
cp cmake-3.26.3-linux-x86_64/share/cmake-3.26 /usr/local/share/

虽然但是,可能有点其他的问题?但是可以正常用了,后续出问题了再看

安装g++/gcc 9.4

这里编译起来比较恼火,但是安装过程还算顺利,参考博客:gcc特定版本Linux源码编译安装,顺着下来完全没有问题,而且这种方法不用卸载旧版本的gcc,可以选择新旧版本,还比较方便。

  1. 下载gcc9.4源码

清华大学开源软件镜像站找到对应版本下载即可
在这里插入图片描述

  1. 下载gcc9.4需要的依赖包,全部放在gcc-9.4.0文件夹中
    • gmp-6.1.0.tar.bz2
    • mpfr-3.1.4.tar.bz2
    • mpc-1.0.3.tar.gz
    • isl-0.18.tar.bz2
      注意不同gcc版本需要的依赖包版本也不同,具体可以进入gcc源码文件夹中 contrib/download_prerequisites 文件中查看,上述版本仅针对gcc9.4
      前三个包可以在清华镜像Index of /gnu/找到
      最后一个包可以在gitee RichardYann / mirrors找到
  2. 执行命令./contrib/download_prerequisites安装依赖包
  3. 编译安装gcc,这个步骤需要留出足够大的空间,可能要8gb左右,不然会编译失败
# 在gcc源码包里创建build文件
mkdir build && cd build
# 配置安装路径
../configure --prefix=/usr/local/gcc-9.4 --enable-languages=c,c++ --disable-multilib
# 安装
make -j8 && make install
  1. 使用update-alternatives将其配置为默认gcc工具
# 首先注册gcc-9.4
update-alternatives --install /usr/bin/gcc gcc /usr/local/gcc-9.4/bin/gcc 100 --slave /usr/bin/g++ g++ /usr/local/gcc-9.4/bin/g++ --slave /usr/bin/gcov gcov /usr/local/gcc-9.4/bin/gcov
# 再注册原本的gcc-7
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 80 --slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-7 --slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-7 --slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-7

随后输入update-alternatives --config gcc,显示:

There are 2 choices for the alternative gcc (providing /usr/bin/gcc).

  Selection    Path                        Priority   Status
------------------------------------------------------------
* 0            /usr/local/gcc-9.4/bin/gcc   100       auto mode
  1            /usr/bin/gcc-7               80        manual mode
  2            /usr/local/gcc-9.4/bin/gcc   100       manual mode

只需在终端交互中输入相应的序号即可切换 gcc版本。(0是auto mode,会自动选择优先级最高的版本)


到目前为止,Viper依赖的cmake和gcc都安装好了,还有concurrentqueue 1.0.3

安装viper

  1. 将viper的源码复制到磁盘文件中
# 首先在磁盘文件中创建一个/home/kvs文件夹,然后在本机中执行下面的命令
sudo cp viper ~/gem5/full-system-image/disks/local_mnt/home/kvs/ -r
  1. 先编译一次
mkdir build && cd build
cmake -DVIPER_BUILD_PLAYGROUND=ON ..

此时会报错,无法联网下载concurrentqueue,但是在build文件夹下面以及创建了_deps文件夹,我们直接将本机下载好的concurrentqueue-src复制到_deps文件夹下;

  1. 修改CMakeLists.txt文件,注释下载concurrentqueue的命令在这里插入图片描述

  2. 修改CMakeLists.txt文件,添加-mno-bmi2如下:
    在这里插入图片描述
    这一步的原因在bug记录中说明。

  3. 重新编译,成功生成playground可执行文件

mkdir build && cd build
cmake -DVIPER_BUILD_PLAYGROUND=ON ..
cmake --build .
  1. 测试Viper的使用
    • 因为要让viper跑在cxl设备上,修改playground中创建viper_db的文件路径为:"/dev/cxl_mem0"
      在这里插入图片描述

    • 调整viper的访问模式为devdax,也就是使用字符设备,修改viper.hppinit_pool()函数如下:
      在这里插入图片描述

    • 另外devdax支持的mmap标志MAP_SYNC,我们的驱动无法支持,所以修改viper.hppVIPER_MAP_FLAGS如下:
      在这里插入图片描述

    • 最后,注意此时虽然成功得到了playground可执行文件,但是众所周知在gem5下运行程序非常的慢,而viper.hpp中有个操作非常非常的花时间,而且藏的很隐蔽,是在初始化一个map_
      数据结构时的一个for循环,要想快一点跑出结果,需要修改viper.hpp的源码的一个魔法数字(即不明原因的常数),我修改为1024会快一点,目前看来无伤大雅
      在这里插入图片描述
      此时重新编译并执行playground便可以较快的得到结果:

cmake --build .
./playground

另外值得一提的是,发现gem5的X86TimingSimpleCPU是Intel至强服务器的架构,它支持clwb扩展指令集,所以前文中对_mm_clwb的修改可以保持原样。

四、bug记录

1. 有关gcc中libstdc++版本的问题

gcc安装完成后,在编译viper时可能会出现libstdc++版本太低的问题,使用strings /usr/lib64/libstdc++.so.6 |grep GLIBC查看当前libstdc++支持的GLIBCXX版本,发现版本号在所需的版本那里就停了,其实是系统没有找到新安装的gcc的libstdc++,做如下操作:

# 把安装后的libstdc++.so.6.0.28 拷贝到/usr/lib
cp /usr/local/gcc-9.4/lib64/libstdc++.so.6.0.28  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
# 创建软链接
ln -sf libstdc++.so.6.0.28 libstdc++.so.6

这样再使用strings /usr/lib64/libstdc++.so.6 |grep GLIBC查看,应该就会有所改变。
参考如何升级linux的libstdc++.so

2. 有关Illegal instruction的问题

使用这个viper最难蚌的一点是,它依赖的软件包等都比较新,需要更新cmake和gcc就算了,最大的问题是,它在我本机的硬件环境下编译出来了一个shlx指令,该指令gem5的cpu不支持,想尽了办法规避这个shlx指令。

在运行playground测试viper时,发现总是会出现Illegal instruction这个报错,通过多方查询,从这个博客中获得一些信息[x86][linux]AVX512指令引起的进程crash,也就是有个汇编指令我的cpu不支持。

  1. 使用dmesg | tail -20命令查看内核的报错:
[ 1751.566928] traps: playground[1140] trap invalid opcode ip:419154 sp:7ffc289ba970 error:0 in playground[400000+32000]
  1. 通过反汇编可执行文件:objdump -D playground > playground.txt
  2. 定位到419154: c4 e2 f9 f7 c2 shlx %rax,%rdx,%rax这个罪魁祸首
    所以想方设法规避编译出这个shlx指令,尝试了多种方法:

官方的指令说明:SARX/SHLX/SHRX,提到CPU运行的实模式和虚拟8086模式,SHLX指令不支持这两个模式,也就是只能运行保护模式下,这可难倒我了。。。

  • 通过改写viper源码,用vector容器代替某些数据结构,编译结果发现出现了3条shlx指令。。。
  • 通过gcc查看CPU体系结构:gcc -march=native -c -Q --help=target | grep march,通过march=nocano指定体系结构进行编译,同样不行。(参考gcc-编译时使用的指令集)

后来发现可以通过选项禁止某些指令集的编译,参考gcc编译时指定指令集,查到shlx指令包含在bmi2扩展指令集中,遂添加-mno-bmi2选项,发现shlx消失了!成功运行!

编译viper虽然是在磁盘文件的环境下编译的,但是CPU硬件架构还是本电脑的Intel® Core™ i5-9300H CPU,可以使用cat /proc/cpuinfo指令查看cpu支持的指令集有哪些,
比如我本机支持:
在这里插入图片描述
包括bmi2扩展指令集,但是同样的查看gem5的cpu指令集(X86TimingSimpleCPU),如下图:
在这里插入图片描述
发现并没有bmi2,所以shlx指令不支持。

五、其他KVS

  1. levelDB github、levelDB简单使用
  2. Pmemkv官方介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/447803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

水电设计院信息管理系统1.0

水电设计公司信息管理系统软件使用说明书 代码太多就不贴了,请在我的资源里下载,已部署在企业进行试运行。https://download.csdn.net/download/weixin_44735475/87704302 目录 1.引言 1 2.项目背景 1 3.系统功能 2 3.1系统功能 2 3.2系统性能 2 3.3系…

Python GUI自动化神器pyautogui,精准识别图片并自动点赞(32)

小朋友们好,大朋友们好! 我是猫妹,一名爱上Python编程的小学生。 欢迎和猫妹一起,趣味学Python。 今日主题 你听过GUI自动化吗? GUI自动化就是用软件模拟鼠标和键盘的操作。 提到Python GUI自动化,不…

Flink State 笔记帖

1 State 分类 Operator State 主要用在Source、Sink等没有key分布的位置。 Keyed State 用在keyBy后的KeyedStream里,每个存储状态与一个key想关联。 ValueState ListState MapState ReducingState AggeratingState 2 State Backend StateBackend分类 HashMa…

JVM之JDK 监控和故障处理工具总结

JDK 命令行工具 这些命令在 JDK 安装目录下的 bin 目录下: jps (JVM Process Status): 类似 UNIX 的 ps 命令。用于查看所有 Java 进程的启动类、传入参数和Java 虚拟机参数等信息;jstat(JVM Statistics Monitoring Tool&#x…

虚拟人与娱乐传媒融合,推动综艺新模式

经过多年的更新迭代和市场的推动,虚拟人技术正在逐渐迈向成熟:3D虚拟形象的制作变得越来越精致且真实,并且出现了越来越多功能丰富使用便捷的动捕设备。因此,包括综艺影视在内的诸多领域,开始尝试将虚拟人技术融入行业…

DETR:end-to-end object detection with transformers

DETR 论文精读【论文精读】_哔哩哔哩_bilibili更多论文:https://github.com/mli/paper-reading/, 视频播放量 90699、弹幕量 493、点赞数 3566、投硬币枚数 2939、收藏人数 2564、转发人数 663, 视频作者 跟李沐学AI, 作者简介 ,相关视频:在线…

【设计原则】依赖倒置原则--高层代码和底层代码到底谁该依赖谁?

文章目录 前言一、谁依赖谁二、依赖于抽象总结 前言 依赖这个词,程序员们都好理解,意思就是,我这段代码用到了谁,我就依赖了谁。依赖容易有,但能不能把依赖弄对,就需要动点脑子了。 如果依赖关系没有处理…

【红队APT】反朔源隐藏C2项目CDN域前置云函数数据中转DNS转发

文章目录 域前置-CDN隐藏C2真实IP 防止被溯源什么是域前置条件原理 完整复现域前置溯源 DNS协议-域名记录解析云函数-腾讯云操作云函数如何溯源 端口转发-Iptables中间件反向代理-Apache 域前置-CDN隐藏C2真实IP 防止被溯源 国内外云服务上大部分已经不支持域前置了&#xff0…

局域网哪些特点?快解析内网穿透实现外网访问局域网SVN

无线局域网传统是有线局域网络的补充和扩展,具有灵活性、可移动性及较低的投资成本等优势,受到了家庭网络用户、中小型办公室用户、广大企业用户及电信运营商的青睐,成为当前整个数据通信领域发展最快的产业之一。 局域网一般为一个单位所建&…

(20230418 SALE算法)个人模型学习笔记记录 500

写给自己: 一、先不做对称的结构试一下,上一个ALE的模型,记得有次没有做对称结构,居然需要11天才能算完,当时吓得我赶紧删除了,做了对称结构。先试一下这个S-ALE能否不做成对称的。但是我感觉或许也会计算很长时间。要不我先试一下。 写给自己: 一、先不做对称的结构…

【UE 控件蓝图】通过键盘选中要点击的按钮 通过Enter键点击

上一篇【UE 控件蓝图】菜单及功能实现博客已经完成了菜单的制作,但是我们只能通过鼠标来点击菜单选项,本篇博客实现的是能够通过键盘的上下键来选中按钮,然后按下“Enter”键来实现点击按钮的效果。 效果 可以看到并没有移动鼠标也可以通过…

Node【Global全局对象】之【Console】

文章目录 🌟前言🌟Console模块🌟console对象方法🌟console.log()🌟console.dir()🌟console.time()🌟console.assert()🌟console.trace()🌟写在最后 🌟前言 哈…

升级数智化底座领先实践:北京地铁加速财务数智化转型

近年来,数字经济蓬勃发展,正在成为重组全球要素资源、重塑全球经济结构、改变全球竞争格局的关键力量。中共中央、国务院印发的《数字中国建设整体布局规划》再次明确指出,做强做优做大数字经济。推动数字技术和实体经济深度融合,…

如何使用Postman做多接口测试【实战】

1. 摘要 本文讲解使用postman做接口测试和批量接口测试的方法。 2.实践内容 2.1 环境变量和全局变量的设置: a. 环境变量的设置方法如下图。点击设置一个环境变量,名为"user_pwd", 里面设置username 和passwd的值,然后在请求中…

gdb切换窗口焦点

为了辅助调试,一般会使用layout src,调起TUI显示代码: 然而这种情况下我们写命令很不方便,无法方便地使用上一条命令、退格等。 按动上下左右方向键盘只会移动代码框,然而在伪终端下,可以用鼠标滚轮来上下…

同步TMS-fMRI研究脑功能网络的指南

导读 经颅磁刺激(TMS)可直接激活人脑新皮层中的神经元,并已被证明是认知神经科学因果假设检验的基础。通过同时使用TMS和fMRI,皮层TMS对远端皮层和皮层下结构活动的影响可以通过改变TMS输出强度来量化。然而,TMS在fMRI时间序列中产生了显著的…

Google Earth Engine谷歌地球引擎GEE合并多个不同Asset的方法

本文介绍在GEE中,将多个存储有点要素的Asset加以合并,使得其成为一个Asset的方法。 本文是谷歌地球引擎(Google Earth Engine,GEE)系列教学文章的第十五篇,更多GEE文章请参考专栏:GEE学习与应用…

银行数字化转型导师坚鹏:商业银行数字化风控(2天)

商业银行数字化风控 课程背景: 数字化背景下,很多银行存在以下问题: 不清楚商业银行数字化风控发展现状? 不清楚对公业务数字化风控工作如何开展? 不知道零售业务数字化风控工作如何开展? 课程特色…

web攻防-通用漏洞验证码识别复用调用找回密码重定向状态值

目录 一、知识点概述 二、找回密码过程中涉及到的安全问题 三、案例演示 <验证码回显> <修改Response状态值> <验证码爆破> 四、真实案例1 <更改状态值> <验证码接口调用> 五、真实案例2 <用户名重定向> 六、安全修复方案 一、…

C语言实现栈--数据结构

魔王的介绍&#xff1a;&#x1f636;‍&#x1f32b;️一名双非本科大一小白。魔王的目标&#xff1a;&#x1f92f;努力赶上周围卷王的脚步。魔王的主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王.&#x1f525;&#x1f525;&#x1f525; ❤️‍&#x1…