[QNX] mmap+cache/nocache+memcpy/asm_memcpy速度对比

mmap nocache介绍

以linux系统的nocache介绍:

在Linux系统中,使用mmap映射文件到内存时可以指定不使用缓存。这可以通过在调用mmap时将MAP_NOCACHE标志传递给mmap函数来实现。
MAP_NOCACHE标志告诉内核不要将映射的内存页缓存到文件系统缓存中,而是直接将内存与文件关联。这对于需要频繁读写大量数据的应用程序是有益的,因为它避免了在读写数据时额外的缓存开销。

例如:

#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
    int fd = open("file.txt", O_RDWR);
    char *ptr = mmap(NULL, 100, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOCACHE, fd, 0);
    // use ptr to read and write data directly from/to the file
    ...
    munmap(ptr, 100);
    close(fd);
    return 0;
}

qnx系统介绍:
https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_typed_mem_open.html

数据

memcpy cached speed: 2133.333333 MB/s (千兆级别)
memcpy nocached speed: 116.363636 MB/s (百兆级别)
invalidate memcpy cached speed: 1333.333333 MB/s (千兆级别)
invalidate memcpy nocached speed: 112.280702 MB/s (百兆级别)
asm memcpy cached speed: 2133.333333 MB/s (千兆级别)
asm memcpy nocached speed: 225.352113 MB/s (百兆级别)

名词

mmap cached指mmap使用PROT_READ | PROT_WRITE这个flag

mmap nocached是指mmap使用PROT_READ | PROT_WRITE | PROT_NOCACHE这个flag

  • memcpy是指单纯调用memcpy,如
for (size_t i = 0; i < count; i++) {
    memcpy(dst, src[i], bytes);
}
  • invalidate memcpy是指memcpy前先用msync设置共享内存属性,如
for (size_t i = 0; i < count; i++) {
    msync(src[i], bytes, MS_INVALIDATE);
    memcpy(dst, src[i], bytes);
}
  • asm memcpy是指汇编版本的memcpy,如
inline void aarch64_fast_memcpy(void *dst, const void *src, size_t size) {
#ifdef _QNX_
    void *ss = (void *)src, *dd = (void *)dst;
    size_t sz = size;

    asm volatile("loop_start: "
                 "ldp q3, q4,[%0,#0x0]\n"
                 "ldp q5, q6,  [%0,#0x20]\n"
                 "ldp q7, q8,  [%0,#0x40]\n"
                 "ldp q9, q10, [%0,#0x60]\n"
                 "stp q3, q4,  [%1,#0x0]\n"
                 "stp q5, q6,  [%1,#0x20]\n"
                 "stp q7, q8, [%1,#0x40]\n"
                 "stp q9, q10, [%1,#0x60]\n"
                 "add %0, %0, #0x80\n"
                 "add %1, %1, #0x80\n"
                 "subs %2, %2, #0x80\n"
                 "b.ne loop_start\n"
                 "dsb sy\n"
                 : /* no output */
                 : "r"(ss), "r"(dd), "r"(sz));
#endif
}
// ......   
for (size_t i = 0; i < count; i++) {
    aarch64_fast_memcpy(dst, src[i], bytes);
}

(完整代码见后面长源码文件)

结论

cached情况下:memcpy和asm memcpy差不多快(没有明显区别),invalidate memcpy最慢。

nocached情况下,asm memcpy最快,memcpy第二快,invalidate memcpy最慢。

测试源码

// mmap_memcpy.c
#include <errno.h>
#include <fcntl.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

#ifndef _QNX_
#define PROT_NOCACHE 0
#endif

inline void aarch64_fast_memcpy(void *dst, const void *src, size_t size) {
#ifdef _QNX_
    void *ss = (void *)src, *dd = (void *)dst;
    size_t sz = size;

    asm volatile("loop_start: "
                 "ldp q3, q4,[%0,#0x0]\n"
                 "ldp q5, q6,  [%0,#0x20]\n"
                 "ldp q7, q8,  [%0,#0x40]\n"
                 "ldp q9, q10, [%0,#0x60]\n"
                 "stp q3, q4,  [%1,#0x0]\n"
                 "stp q5, q6,  [%1,#0x20]\n"
                 "stp q7, q8, [%1,#0x40]\n"
                 "stp q9, q10, [%1,#0x60]\n"
                 "add %0, %0, #0x80\n"
                 "add %1, %1, #0x80\n"
                 "subs %2, %2, #0x80\n"
                 "b.ne loop_start\n"
                 "dsb sy\n"
                 : /* no output */
                 : "r"(ss), "r"(dd), "r"(sz));
#endif
}

off_t offset(unsigned int bytes) {
    static off_t base_offset = 0x1E000000;
    off_t return_base_offset = base_offset;
    base_offset += bytes;
    return return_base_offset;
}

void *mmap_memory(unsigned int bytes, int flag) {
    int fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (fd < 0) {
        printf("open /dev/mem failed: %s\n", strerror(errno));
    }

    void *ptr = mmap(NULL, bytes, flag, MAP_SHARED, fd, offset(bytes));
    close(fd);

    if (MAP_FAILED == ptr) {
        printf("mmap failed: %s\n", strerror(errno));
    }

    return ptr;
}

void *mmap_memory_cached(unsigned int bytes) {
    return mmap_memory(bytes, PROT_READ | PROT_WRITE);
}

void *mmap_memory_nocached(unsigned int bytes) {
    return mmap_memory(bytes, PROT_READ | PROT_WRITE | PROT_NOCACHE);
}

// if C++
#ifdef __cplusplus
#include <chrono>
using namespace std::chrono;
#define start() auto start_ = high_resolution_clock::now();
#define end()                                                                  \
    auto end_ = high_resolution_clock::now();                                  \
    double bytes_mb = bytes * count / 1024.0 / 1024.0;                         \
    double cost_ns = duration_cast<nanoseconds>(end_ - start_).count();        \
    double mps = bytes_mb / cost_ns * 1e9;

#else
#include <time.h>
#include <unistd.h>
double time_diff_ns(struct timespec start, struct timespec end) {
    return (end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec);
}
#define start()                                                                \
    struct timespec start_, end_;                                              \
    clock_gettime(CLOCK_REALTIME, &start_);

#define end()                                                                  \
    clock_gettime(CLOCK_REALTIME, &end_);                                      \
    double bytes_mb = bytes * count / 1024.0 / 1024.0;                         \
    double cost_ns = time_diff_ns(start_, end_);                               \
    double mps = bytes_mb / cost_ns * 1e9;

#endif

double memcpy_speed(void *dst, void **src, unsigned int bytes,
                    unsigned int count) {
    start();
    for (size_t i = 0; i < count; i++) {
        memcpy(dst, src[i], bytes);
    }
    end();
    return mps;
}

double invalidate_memcpy_speed(void *dst, void **src, unsigned int bytes,
                               unsigned int count) {
    start();
    for (size_t i = 0; i < count; i++) {
        msync(src[i], bytes, MS_INVALIDATE);
        memcpy(dst, src[i], bytes);
    }
    end();
    return mps;
}

double asm_memcpy_speed(void *dst, void **src, unsigned int bytes,
                        unsigned int count) {
    start();
    for (size_t i = 0; i < count; i++) {
        aarch64_fast_memcpy(dst, src[i], bytes);
    }
    end();
    return mps;
}

int main(int argc, char *argv[]) {
    const unsigned int count = 2;
    unsigned int bytes = 128 * 1024; // 128 KB
    if (argc > 1) {
        bytes = atoi(argv[1]) * 1024;
    }
    printf("bytes: %d\n", bytes);
    printf("count: %d\n", count);

    void *mmap_cached_src[count];
    void *mmap_nocached_src[count];
    for (size_t i = 0; i < count; i++) {
        mmap_cached_src[i] = mmap_memory_cached(bytes);
        mmap_nocached_src[i] = mmap_memory_nocached(bytes);
    }

    void *dst = malloc(bytes);
    printf("memcpy cached speed: %f MB/s\n",
           memcpy_speed(dst, mmap_cached_src, bytes, count));
    printf("memcpy nocached speed: %f MB/s\n",
           memcpy_speed(dst, mmap_nocached_src, bytes, count));
    printf("invalidate memcpy cached speed: %f MB/s\n",
           invalidate_memcpy_speed(dst, mmap_cached_src, bytes, count));
    printf("invalidate memcpy nocached speed: %f MB/s\n",
           invalidate_memcpy_speed(dst, mmap_nocached_src, bytes, count));
    printf("asm memcpy cached speed: %f MB/s dst[0]=%d\n",
           asm_memcpy_speed(dst, mmap_cached_src, bytes, count), ((char *)dst)[0]);
    printf("asm memcpy nocached speed: %f MB/s\n",
           asm_memcpy_speed(dst, mmap_nocached_src, bytes, count));
    free(dst);
    for (size_t i = 0; i < count; i++) {
        munmap(mmap_cached_src[i], bytes);
        munmap(mmap_nocached_src[i], bytes);
    }

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

扩展学习|结合故事的力量和数字的力量:混合方法研究和混合研究综述

文献来源&#xff1a;Pluye, Pierre, and Quan Nha Hong. "Combining the power of stories and the power of numbers: mixed methods research and mixed studies reviews." Annual review of public health 35 (2014): 29-45. 文献获取&#xff1a;链接&#xff1…

企业宣传新思路!制作三维动画,塑造品牌形象

三维动画又称之为3D动画&#xff0c;通过三维动画技术模拟真实物体的方式使其成为一个有用的工具。其精确性、真实性和可操作性&#xff0c;被广泛应用于影视、工业、电子、广告等诸多领域。 三维动画是在现代技术不断创新发展的基础上而产生的新型艺术表现形式&#xff0c;已…

深入解析C#特殊字符:概念、分类与使用方法

文章目录 前言一、特殊字符的定义二、特殊字符的分类与作用1.转义字符2. 格式字符3. 逻辑运算符4. 运算符5. 字符串6. 注释 三、$&#xff1a;字符串内插&#xff08;String Interpolation&#xff09;四、&#xff1a;逐字字符串&#xff08;Verbatim Strings&#xff09;五、…

爱奇艺文娱知识图谱的构建与应用实践

2012年5月&#xff0c;Google发布了知识图谱(Knowledge Graph)&#xff0c;以提升搜索引擎返回的答案质量和用户查询的效率。有了知识图谱作为辅助&#xff0c;搜索引擎能够洞察用户查询背后的语义信息&#xff0c;返回更为精准、结构化的信息&#xff0c;更大可能地满足用户的…

界面组件Kendo UI for Angular教程 - 构建强大的PDF阅读器(一)

如今当用户需要处理PDF文件时&#xff0c;通常不得不下载应用程序或者浏览器插件&#xff0c;控制用户如何与PDF交互并不是一件容易的事。如果我们提供PDF作为内容&#xff0c;用户可以下载它并使用浏览器或PDF本身提供的控件进行交互。然而&#xff0c;一些企业可能希望控制用…

PN结击穿与电容效应分析

PN结是半导体器件中的一个基本结构&#xff0c;它由P型半导体和N型半导体紧密接触并相互结合在一起形成。P型半导体富含空穴&#xff08;正电荷载体&#xff09;&#xff0c;是通过掺入受主杂质原子得到的&#xff1b;而N型半导体富含自由电子&#xff08;负电荷载体&#xff0…

『春招实习』2023年3月春招实习求职经历

『春招实习』2023年3月春招实习求职经历 简介货拉拉一面杭州吉里一面传墨科技一面 简介 3月初我便开始陆续投递简历&#xff0c;直观的感受就是【投递的太晚了】&#xff0c;很多公司很早就开始招聘实习生了。 但是自己一直在担心没准备好&#xff0c;所以就想着再准备一天就投…

Covalent Network(CQT)为 Arbitrum 生态提供 250 万美元的资助,以促进 Web3 的创新与发展

Covalent Network&#xff08;CQT&#xff09;作为 Web3 领先的“数据可用性”层&#xff0c;宣布将提供 250 万美元的资金以支持 Arbitrum 生态项目&#xff0c;包括 Arbitrum One、Nova、Orbit 或 Stylus。此举旨在通过提供资源和帮助&#xff0c;推动利用 Arbitrum 网络上 C…

第二证券|股票w是什么意思?

字母W开头是指在科创板上市&#xff0c;发行人具有表决权差异组织的&#xff0c;即同股不同权的股票。上市后不再具有表决权差异组织的&#xff0c;该特别标识撤销。 科创板其他一些特别的字母标识&#xff1a; 1、发行人尚未盈余的&#xff0c;其股票或存托凭据的特别标识为…

windows10为什么微信可以上网浏览器无法上网?

windows10为什么微信可以上网浏览器无法上网&#xff1f; 问题描述解决办法 问题描述 打开电脑学习时&#xff0c;微信可以上网&#xff0c;浏览器无法上网&#xff0c;如何解决&#xff1f; 解决办法 1.控制面板->网络和Internet 2.Internet选项 3.Internet属性->连…

SQLI-labs-第十三关和第十四关

知识点&#xff1a;POST方式的单引号和括号闭合错误,报错注入 第十三关 思路&#xff1a; 1、判断注入点 使用Burpsuite抓包 首先加入一个单引号&#xff0c;爆出了数据库语句错误&#xff0c;说明存在注入点&#xff0c;根据提示&#xff0c;这里可能是’&#xff09;闭合错…

【prometheus】Pushgateway安装和使用

目录 一、Pushgateway概述 1.1 Pushgateway简介 1.2 Pushgateway优点 1.3 pushgateway缺点 二、测试环境 三、安装测试 3.1 pushgateway安装 3.2 prometheus添加pushgateway 3.3 推送指定的数据格式到pushgateway 1.添加单条数据 2.添加复杂数据 3.SDk-prometheus-…

Linux网络部分——DHCP、FTP

目录 一、DHCP动态主机配置协议 1. DHCP工作原理&#xff08;流程&#xff09; 2. 使用DHCP的好处 3.DHCP的分配方式 4.DHCP安装和配置【☆】 二、FTP文件传输协议 1. FTP传输模式 2.FTP安装与配置【☆】 3. FTP设置白名单和黑名单【☆】 一、DHCP动态主机配置协议 DH…

安全数据交换系统哪个好?该如何选型?

安全数据交换系统是用于在不同网络或组织之间安全、高效地传输和共享数据的解决方案。安全数据交换系统对于任何需要处理敏感数据、确保数据安全、并满足合规要求的组织来说都是至关重要的。 这种系统通常用于以下目的&#xff1a; 1&#xff09;数据传输&#xff1a;允许用户…

项目经理【人】原则

系列文章目录 【引论一】项目管理的意义 【引论二】项目管理的逻辑 【环境】概述 【环境】原则 【环境】任务 【环境】绩效 【人】概述 【人】原则 一、共创模式 1.1 共创模式 二、干系人的影响力强度和态度 2.1 干系人影响力 2.2 干系人态度 2.3 干系人管理 三、干系人权力…

自动驾驶融合定位系列教程五:惯性导航误差分析

自动驾驶融合定位系列教程五&#xff1a;惯性导航误差分析 一、概述 在定位领域的几乎所有多传感器融合系统中&#xff0c;都有IMU存在&#xff0c;而且&#xff0c;IMU是定位系统的主线与核心&#xff08;对此可能很多人并不同意&#xff0c;但是我仍然坚定地坚持这一观点&a…

spring中的bean是线程安全的嘛

在Spring框架中&#xff0c;bean默认情况下不是线程安全的。Spring容器在初始化bean时&#xff0c;会为其创建一个单例实例&#xff0c;这个实例在整个应用中是唯一的&#xff0c;并且只会被初始化一次。由于这个特性&#xff0c;bean在默认情况下不是线程安全的。 然而&#…

亚马逊测评工作室如何轻松实现高收益,跨境电商揭秘汇率差赚钱术

随着跨境电商在国内市场的持续繁荣&#xff0c;众多电商卖家纷纷将目光投向了这一充满活力的领域。面对国内市场的激烈竞争&#xff0c;许多卖家选择向外拓展&#xff0c;寻求更广阔的发展空间。其中&#xff0c;亚马逊成为了众多卖家的不二选择&#xff0c;毕竟老外的市场还是…

吴恩达2022机器学习专项课程C2(高级学习算法)W1(神经网络):2.3 案例图像识别

目录 电脑如何表示一张图像1.像素2.像素亮度值3.展开像素亮度值 神经网络构建人脸识别1.需求2.整体过程3.隐藏层识别图像4.小结 神经网络构建识别汽车神经网络在计算机视觉应用中的工作原理 电脑如何表示一张图像 1.像素 像素是图像最小单位&#xff0c;用于表示图像中的点或…

Android Ant编译环境配置(Win)

1、 载ant包: 2、设置环境变量&#xff1a; 3、检查是否设置成功及版本 4、执行命令&#xff1a; android update project -p . -n “projectname”&#xff08;例如&#xff1a;android update project --target 1 -p . -n “Couplet”&#xff09;(只输入红色部分也是可以的…
最新文章