介绍与评测Intel HLE与RTM技术

news2024/11/16 7:39:04

HLE(即Hardware Lock Elision,硬件锁省略)以及RTM(即Restricted Transactional Memory,受限的事务性存储器)是Intel在x86微架构中所引入的两条指令集系统,它们均属于TSX(Transactional Synchronization Extensions,事务性同步扩展)指令集扩展。这套指令集扩展往往用于包含原子操作代码的临界区(Critical Section),通过将原子锁进行省略而使得多核多线程并行对此临界区的操作能进行提速。
下图比较详细地介绍了这两套指令集的执行逻辑以及使用方式。

coding transactions with TSX

这个图取自于Muttik等人的一份paper,各位可以参考此文:CREATING A SPIDER GOAT: USING TRANSACTIONAL MEMORY SUPPORT FOR SECURITY。

下面我们将分别基于RTM和HLE来给出一些评测。各位要注意的是,尽管TSX在Intel Haswell微架构上就引入了,但那时候的实现尚不成熟,而且还有较严重的BUG。直到Skylake时代,部分处理器能正常时候该特性了。不过为了安全可靠起见,笔者建议各位在Kabylake或在此之后的处理器上运行以下代码。
由于之前关于“幽灵”、“熔断”等CPU高危漏洞的爆出,因此像更注重安全性的Mac已经把TSX全面屏蔽了,包括汇编器也直接不支持 XACQUIRE/XRELEASE 指令。因此笔者这里只能在装有Windows 10的联想笔记本上通过Visual Studio 2017 Community Edition进行测试。使用的处理器为Core i5 8250U。不过可惜的是,这款CPU没能支持TSX指令集扩展,我们只能稍作演示。
在Windows 10上如何通过Visual Studio 2017创建一个普通的C语言控制台项目,请参考这篇博文。我们这里就使用最基本的MSVC编译器即可。
下面先给出用于测试的test.asm汇编文件内容:

; test.asm

.code

    ; void cpu_pause(void)
    cpu_pause	proc public

    pause
    ret

    cpu_pause	endp

    ; void NormalAddTest(int *pArray, int count)
    NormalAddTest	proc public

    ; pArray => rcx
    ; count => edx
    mov     eax, 1

NormalAddTest_LOOP:

    add     [rcx], eax
    add     rcx, 4
    sub     edx, 1
    jne     NormalAddTest_LOOP

    ret

    NormalAddTest	endp

    ; void AtomicAddTest(int *pArray, int count)
    AtomicAddTest   proc public

    ; pArray => rcx
    ; count => edx
    mov     eax, 1

AtomicAddTest_LOOP:

    lock add    [rcx], eax
    add     rcx, 4
    sub     edx, 1
    jne     AtomicAddTest_LOOP

    ret

    AtomicAddTest   endp

    ; void HLEAtomicAddTest(int *pArray, int count)
    HLEAtomicAddTest	proc public

    ; pArray => rcx
    ; count => edx
    mov     eax, 1

HLEAtomicAddTest_LOOP:

    xacquire lock add    [rcx], eax
    add     rcx, 4
    sub     edx, 1
    jne     HLEAtomicAddTest_LOOP

    ret

    HLEAtomicAddTest    endp

    ; void FlagSetTest(volatile int *pFlag, int *pValue, int repeatCount)
    FlagSetTest         proc public

    ; pFlag => rcx
    ; pArray => rdx
    ; count => r8d

    mov     eax, 1
    xor     r9d, r9d
    jmp     FlagSetTest_LOOP

FlagSetTest_FAIL_HANDLER:
    pause

FlagSetTest_LOOP:

    xacquire lock bts   [rcx], r9d
    jc      FlagSetTest_FAIL_HANDLER

    add     [rdx], eax

    xrelease    mov     [rcx], r9d

    sub     r8d, 1
    jne     FlagSetTest_LOOP

    ret

    FlagSetTest         endp

END

下面给出main.c源文件内容:

// 你好,世界

#include <Windows.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#define TEST_LOOP_COUNT     10

extern void cpu_pause(void);
extern void NormalAddTest(int *pArray, int count);
extern void AtomicAddTest(int *pArray, int count);
extern void HLEAtomicAddTest(int *pArray, int count);

extern void FlagSetTest(volatile int *pFlag, int *pValue, int repeatCount);

static volatile bool sIsComplete = false;

struct MyFuncCallParam
{
    void(*pFunc)(int*, int);
    int *pArray;
    int count;
};

static DWORD WINAPI TestThreadProc(LPVOID lpParam)
{
    struct MyFuncCallParam *callInfo = (struct MyFuncCallParam*)lpParam;
    void(*const pTestFunc)(int*, int) = callInfo->pFunc;
    int* const pBuffer = callInfo->pArray;
    const int count = callInfo->count;

    for (int i = 0; i < 100; i++)
        pTestFunc(pBuffer, count);

    sIsComplete = true;
    
    return 0;
}

static void TestAddFunction(void(*pTestFunc)(int*, int), int *pArray, int count)
{
    sIsComplete = false;

    struct MyFuncCallParam param = { pTestFunc, pArray, count };

    HANDLE hThread = CreateThread(NULL, 0, TestThreadProc, &param, 0, NULL);

    for (int i = 0; i < 100; i++)
        pTestFunc(pArray, count);

    while (!sIsComplete)
        cpu_pause();

    CloseHandle(hThread);
}


int main(int argc, const char * argv[])
{
    // 数据初始化
    const int count = 1024 * 1024;
    int *data = malloc(count * sizeof(data[0]));
    for (int i = 0; i < count; i++)
        data[i] = i;

    // 数据完整性测试

    TestAddFunction(AtomicAddTest, data, count);

    int errCount = 0;
    for (int i = 0; i < count; i++)
    {
        if (data[i] != i + 200)
            errCount++;
    }

    // 数据处理性能测试
    DWORD tBegin[TEST_LOOP_COUNT], tEnd[TEST_LOOP_COUNT];

    for (int i = 0; i < TEST_LOOP_COUNT; i++)
    {
        tBegin[i] = GetTickCount();

        TestAddFunction(AtomicAddTest, data, count);

        tEnd[i] = GetTickCount();
    }

    DWORD timeSpent = tEnd[0] - tBegin[0];
    for (int i = 1; i < TEST_LOOP_COUNT; i++)
    {
        const DWORD ts = tEnd[0] - tBegin[0];
        if (timeSpent > ts)
            timeSpent = ts;
    }

    printf("Time spent: %ums\n", timeSpent);
    printf("Error count: %d\n", errCount);

    volatile int flag = 0;
    data[0] = 0;

    FlagSetTest(&flag, data, 1);

    free(data);
}

各位在编译构建之后,最好在命令行下执行,这样能保证应用程序的执行不受其他剖析器等进程的影响。

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

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

相关文章

Unity日记22(携程概念)

目录 学习视频 携程 1异步 2调用方法 3优点 4停止方法 5返回值 实例&#xff1a;每过一秒打印当前运行时间 实例&#xff1a;停止数字打印携程 错误方法&#xff1a;&#xff08;携程只能开一个&#xff09; 参考方法 学习视频 https://www.bilibili.com/video/BV1eu…

什么是轻量云服务器,有哪些优势,适用于什么场景?

​  随着互联网的迅速发展&#xff0c;越来越多的企业选择将自己的业务部署到云服务器上。而轻量级云服务器作为云计算领域的一种新的服务模式&#xff0c;也开始受到越来越多企业的青睐。那么&#xff0c;究竟何为轻量级云服务器?其优势又在哪里?又适用于哪些场景?以下将…

前端--移动端--3移动web开发rem适配布局

目标&#xff1a; 能够适应rem单位 能够使用媒体查询的基本语法 能够使用less的基本语法 能够使用less中的嵌套 能够使用less中的运算 能够使用2种rem适配方案 能够独立完成苏宁移动端首页 目录&#xff1a; rem基础 媒体查询 less基础 rem适配方案 苏宁首页案例…

如何修改AS2接收的文件名?

知行之桥EDI系统的AS2端口&#xff0c;负责接收和发送EDI文件。企业通过AS2端口接收来自交易伙伴的文件时&#xff0c;其文件名会和交易伙伴发出的文件名完全一致&#xff1b;如果交易伙伴发过来的请求中没有文件名或者文件名没有出现在AS2 协议规定的位置&#xff0c;AS2端口会…

K_A33_001 基于STM32等单片机驱动RC522射频卡 读写IC卡 串口显示

K_A33_001 基于STM32等单片机驱动RC522射频卡 读写IC卡 串口显示 所有资源导航一、资源说明二、基本参数参数引脚说明 三、驱动说明时序:对应程序: 四、部分代码说明1、接线引脚定义1.1、STC89C52RCRC522射频模块1.2、STM32F103C8T6RC522射频模块 五、基础知识学习与相关资料下…

Django分页+增删改查

Django分页增删改查 演示 源码下载地址&#xff1a;https://download.csdn.net/download/qq_35622606/87719248 其他小笔记&#xff1a; django-admin.exe startproject mysite python .\manage.py startapp app01 python manage.py makemigrations python manage.py migrate…

Docker系列---Docker Compose | 容器编排 | 理论详解

目录 1.Docker Compose 概述&#xff08;YML&#xff09; 2.Docker Compose 安装 3.Docker Compose 配置常用字段 4.Docker Compose 常用命令 5.基于 Compose 创建 镜像 1.首先安装好Compose 2.使用Dockerfile环境&#xff1a; 1.Docker Compose 概述&#xff08;YML&am…

docker + K8S + Rancher + Harbor的安装

docker K8S Rancher Harbor的安装 1. 系统初始化 关闭防火墙 systemctl stop firewalld禁用防火墙开机自启 systemctl disable firewalld永久-关闭selinux sed -i s/enforcing/disabled/ /etc/selinux/config # 重启 reboot关闭swap分区 # 永久 sed -ri s/.*swap.*/#&/…

重启电脑数据丢失怎么恢复?这篇指南很受用!

案例分享&#xff1a;“你好&#xff0c;我重新启动了我的win10电脑&#xff0c;电脑为什么再次开机后&#xff0c;下载的软件就不见了&#xff1f;不仅如此&#xff0c;我的文档也消失不见了&#xff0c;这令我很困惑。请问重启电脑数据丢失怎么恢复&#xff1f;请大家帮帮我&…

系统分析师考试,信息安全常错题

计算机网络---其他 Stub区域是一种比较特殊的区域&#xff0c;因为它不能像其他区域那样&#xff0c;经过该区域中的ABR接收其他OSPF AS路由。在Stub区域的内部路由器仅需要配置一条到达该区域ABR的默认路由&#xff08;0.0.0.0.0.0.0.0&#xff09;来实现与同一AS中不同区域间…

CloudCompare插件开发之如何设计界面ui与功能实现?

文章目录 0.引言1.使用文件说明2.添加界面ui相关文件到插件目录3.修改工程相关文件并生成4.结果展示 0.引言 CloudCompare源代码编译成功后&#xff0c;即可进行二次开发&#xff0c;可通过修改源码实现二次开发基础功能&#xff08;见&#xff1a;CloudCompare如何进行二次开发…

#mysql binlog 备份恢复数据流程#

模式&#xff1a;mysql全量备份binlog日志完整恢复数据 首先&#xff0c;数据库在误操作之前必须已经开启了binlog日志功能&#xff0c;且binlog日志的保存周期必须大于全备份的时间周期&#xff01; 所谓恢复&#xff0c;就是让将全备份的数据全部恢复后&#xff0c;再使用my…

HTB-Time

HTB-Time 信息收集80端口 立足pericles -> root 信息收集 80端口 有两个功能&#xff0c;一个是美化JSON数据。 一个是验证JSON&#xff0c;并且输入{“abc”:“abc”}之类的会出现报错。 Validation failed: Unhandled Java exception: com.fasterxml.jackson.core.JsonPa…

当⻉借⼒阿⾥云落地云原⽣架构转型,运维降本、效率稳定性双升

作者&#xff1a;当贝技术团队 随着业务飞速发展&#xff0c;当贝的传统 IT 资产也渐显臃肿&#xff0c;为了避免制约发展的瓶颈&#xff0c;痛定思痛&#xff0c;技术团队果断变革&#xff1a;核心业务云原生化之后&#xff0c;运维效率、整体稳定性和研发效率均得到了全面提…

网络基础知识

网络基础知识 一、什么是二层互通与三层互通&#xff1f;1.1 二层网络互通1.2 三层网络互通 二、什么是Overlay网络&#xff1f;2.1 Underlay网络2.2 Overlay网络2.3 Underlay网络 vs Overlay网络 三、什么是SNMP&#xff1f;3.1 SNMP概念3.2 为什么需要SNMP&#xff1f;3.3 SN…

基于ubuntu18.04.6 LTS服务器安装nvidia驱动

1对于一个刚刚配置的服务器&#xff0c;首先nvidia-smi&#xff0c;自然无法显示Driver Version、最高cuda版本等信息。 nvidia-smi: command not found 需要我们自己安装nvidia驱动 2禁用老驱动 禁用自带nouveau驱动 sudo vim /etc/modprobe.d/blacklist.conf 打开后在CONF文…

本地配置nacos例子

nacos的加载顺序 0、application.properties 1、bootstrap.properties 2、bootstrap-{profile}.properties #本地启动 nacos的配置文件的生成规则&#xff0c;当我正常启动项目时 nacos的配置文件名字生成规则为 ${spring.application.name}.yaml spring:application:name…

面试redis之两大金刚,你懂吗

前言 Redis持久化&#xff0c;一个老掉牙的问题&#xff0c;但是面试官就是喜欢问。这也是我们学Redis必会的一个知识点。Redis作为内存数据库&#xff0c;它工作时&#xff0c;数据都保存在内存里&#xff0c;这也是它为什么很快的一个原因。但存到内存里肯定是有丢数据的风险…

为什么我们能判断声音的远近

想象一下&#xff0c;当我们走在路上时&#xff0c;听到了头顶的鸟儿在树梢间的叫声&#xff0c;即使无法透过浓密的树叶看见它&#xff0c;也可以大致知道鸟儿的距离。此时身后传来由远到近自行车铃铛声&#xff0c;我们并不需要回过头去看&#xff0c;便为它让开了道路。这些…

查找文件路径——whereis、which、locate、find命令

目录标题 whereis命令——通过环境变量查找所有文件&#xff08;包括可执行文件&#xff09;which命令——查找系统命令文件与whereis命令区别 locate命令——全局搜索find命令&#xff08;全盘搜索&#xff09;find命令中的参数及作用按照文件名搜索按照文件大小搜索按照修改时…