当前位置: 首页 > news >正文

3.2.1.2 汇编版 原子操作 CAS

基本原理说明 

x86ARM 架构上,原子操作通常利用硬件提供的原子指令来实现,比如 LOCK 前缀(x86)或 LDREX/STREX(ARM)。以下是一些关键的原子操作(例如原子递增和比较交换)的汇编实现。


1. x86 架构的原子操作

(1)原子递增

x86 的 LOCK 前缀可以用来保证指令在多核处理器上的原子性。例如原子递增操作:

实现原子递增
global atomic_increment
section .text
atomic_increment:mov eax, 1          ; 设置递增值为 1lock xadd [rdi], eax ; 对地址 rdi 所指向的变量执行原子加操作add rax, 1          ; xadd 返回的是原值,rax = 原值 + 1ret
解释:
  • LOCK XADD [rdi], eax:对 rdi 指向的地址执行原子加操作,将原值存入 eax,并把 eax 加上后写回 rdi
  • 使用 LOCK 前缀可以保证多核环境下的原子性。

(2)比较并交换(CAS)

x86 提供了 CMPXCHG 指令,可以用来实现原子的比较并交换(CAS)。

实现原子 CAS
global atomic_compare_exchange
section .text
atomic_compare_exchange:mov rax, rsi        ; 将期望值放入 raxlock cmpxchg [rdi], rdx ; 如果 [rdi] 的值等于 rax(期望值),将 rdx 写入 [rdi]ret
参数说明:
  • rdi:目标地址。
  • rsi:期望值。
  • rdx:需要交换的值。
解释:
  • LOCK CMPXCHG [rdi], rdx
    • 如果 [rdi] 的值等于 RAX,则将 rdx 写入 [rdi]
    • 否则将 [rdi] 的当前值写入 RAX
  • 返回值:RAX 中存储的是 rdi 的旧值,调用者可以根据是否等于 rsi 判断交换是否成功。

2. ARM 架构的原子操作

ARM 使用 LDREX/STREX 指令对原子操作进行支持。这是一种 负载-存储排他模型,可以保证在加载到存储之间没有其他线程或进程修改目标变量。


(1)原子递增

在 ARM 架构下,使用 LDREX/STREX 实现原子递增:

实现原子递增
.global atomic_increment
atomic_increment:mov r1, #1          ; 将 1 存入 r1(递增值)
1:ldrex r0, [r0]      ; 使用 LDREX 加载 [r0] 的值到 r0add r0, r0, r1      ; r0 = r0 + 1strex r2, r0, [r0]  ; 尝试将 r0 写回 [r0],如果成功 r2 = 0cmp r2, #0          ; 检查写入是否成功bne 1b              ; 如果不成功,重试dmb                 ; 数据内存屏障,确保操作完成bx lr
解释:
  • LDREX:加载目标地址的值,同时标记为“独占”访问。
  • STREX:尝试存储值到目标地址,如果目标地址在此期间被其他核修改,存储操作会失败,返回非 0。
  • 使用循环保证操作成功。

(2)比较并交换(CAS)

实现原子 CAS
.global atomic_compare_exchange
atomic_compare_exchange:ldrex r0, [r1]      ; 从地址 r1 加载值到 r0(旧值)cmp r0, r2          ; 比较 r0 和 r2(期望值)bne 1f              ; 如果不相等,跳转到 1f,返回旧值strex r3, r3, [r1]  ; 尝试将 r3 写入 [r1],如果成功 r3 = 0cmp r3, #0          ; 检查是否存储成功bne atomic_compare_exchange ; 如果失败,重新尝试
1:dmb                 ; 数据内存屏障,保证一致性bx lr
参数说明:
  • r1:目标地址。
  • r2:期望值。
  • r3:要交换的值。
解释:
  • 如果 LDREX 加载的值与 期望值(r2)相等,则尝试存储 r3
  • 如果存储失败,则重复尝试。
  • 成功后返回原值。

3. 汇编操作的注意事项

  1. x86 的强内存模型
    • x86 硬件有一个相对强的内存序,很多情况下 LOCK 前缀可以满足原子操作需求。
  2. ARM 的弱内存模型
    • ARM 是弱内存模型,使用 LDREX/STREX 操作时,通常需要内存屏障(如 DMB)来确保指令顺序和数据同步。
  3. 重试机制
    • 对于 ARM 的 LDREX/STREX 模式,如果存储失败需要通过循环重试。
  4. 指令可用性
    • 需要确保目标平台支持这些指令。比如 CMPXCHG 在早期的 x86 处理器(如 80386)上不可用。

4. 比较总结

操作x86ARM
原子递增LOCK XADDLDREX + ADD + STREX
原子比较交换LOCK CMPXCHGLDREX + CMP + STREX
内存屏障MFENCE(可选)DMB

x86 汇编通常较为简单,因为其强内存序模型降低了编程复杂性;ARM 则需要更明确的同步和屏障操作。

代码实现

my_atomic.h

#include <stdint.h>
#include <stdio.h>// 平台区分
#if defined(__x86_64__)#define ATOMIC_X86
#elif defined(__aarch64__)#define ATOMIC_ARM
#else#error "Unsupported platform"
#endif// ===================== x86 实现 =====================
#ifdef ATOMIC_X86// 原子递增
static inline int atomic_increment(int *addr) {int result;__asm__ __volatile__("lock xaddl %0, %1": "=r"(result), "+m"(*addr): "0"(1): "memory");return result + 1; // 返回递增后的值
}// 原子递减
static inline int atomic_decrement(int *addr) {int result;__asm__ __volatile__("lock xaddl %0, %1": "=r"(result), "+m"(*addr): "0"(-1) // 减 1: "memory");return result - 1; // 返回递减后的值
}// 原子比较交换
static inline int atomic_compare_exchange(int *addr, int expected, int desired) {int old;__asm__ __volatile__("lock cmpxchgl %2, %1": "=a"(old), "+m"(*addr): "r"(desired), "0"(expected): "memory");return old; // 返回旧值
}// 原子读取
static inline int atomic_load(int *addr) {int value;__asm__ __volatile__("movl %1, %0": "=r"(value): "m"(*addr): "memory");return value; // 返回读取值
}#endif // ATOMIC_X86// ===================== ARM 实现 =====================
#ifdef ATOMIC_ARM// 原子递增
static inline int atomic_increment(int *addr) {int old, tmp;do {__asm__ __volatile__("ldrex %0, [%2]      \n" // 读取旧值到 old"add   %1, %0, #1    \n" // tmp = old + 1"strex %0, %1, [%2]  \n" // 尝试写回: "=&r"(old), "=&r"(tmp): "r"(addr): "memory", "cc");} while (old != 0); // 如果写失败,重试return tmp; // 返回递增后的值
}// 原子递减
static inline int atomic_decrement(int *addr) {int old, tmp;do {__asm__ __volatile__("ldrex %0, [%2]      \n" // 读取旧值到 old"sub   %1, %0, #1    \n" // tmp = old - 1"strex %0, %1, [%2]  \n" // 尝试写回: "=&r"(old), "=&r"(tmp): "r"(addr): "memory", "cc");} while (old != 0); // 如果写失败,重试return tmp; // 返回递减后的值
}// 原子比较交换
static inline int atomic_compare_exchange(int *addr, int expected, int desired) {int old, status;do {__asm__ __volatile__("ldrex %0, [%2]       \n" // 加载到 old"cmp   %0, %3         \n" // 比较 old 和 expected"bne   1f             \n" // 如果不相等,跳转到 1"strex %1, %4, [%2]   \n" // 尝试写回 desired"1:": "=&r"(old), "=&r"(status): "r"(addr), "r"(expected), "r"(desired): "memory", "cc");} while (status != 0); // 如果写失败,重试return old; // 返回旧值
}// 原子读取
static inline int atomic_load(int *addr) {int value;__asm__ __volatile__("ldrex %0, [%1] \n" // 加载值到 value: "=&r"(value): "r"(addr): "memory");return value; // 返回读取值
}#endif // ATOMIC_ARM

my_atomic_test.c

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "my_atomic.h"#define NUM_THREADS 4
#define ITERATIONS 1000volatile int shared_counter = 0; // 全局共享计数器// 线程函数:执行递增操作
void* thread_increment(void* arg) {for (int i = 0; i < ITERATIONS; i++) {atomic_increment((int*)&shared_counter);}return NULL;
}// 线程函数:执行递减操作
void* thread_decrement(void* arg) {for (int i = 0; i < ITERATIONS; i++) {atomic_decrement((int*)&shared_counter);}return NULL;
}int main() {pthread_t threads[NUM_THREADS];// 创建增量线程for (int i = 0; i < NUM_THREADS / 2; i++) {if (pthread_create(&threads[i], NULL, thread_increment, NULL) != 0) {perror("pthread_create");exit(EXIT_FAILURE);}}// 创建减量线程for (int i = NUM_THREADS / 2; i < NUM_THREADS; i++) {if (pthread_create(&threads[i], NULL, thread_decrement, NULL) != 0) {perror("pthread_create");exit(EXIT_FAILURE);}}// 等待所有线程完成for (int i = 0; i < NUM_THREADS; i++) {pthread_join(threads[i], NULL);}// 最终结果int final_value = atomic_load((int*)&shared_counter);printf("最终计数器值: %d\n", final_value);return 0;
}

ubuntu x86编译运行

$ gcc -pthread -o a.out my_atomic_test.c
$ ./a.out
最终计数器值: 0


gitlab.0voice.com

相关文章:

3.2.1.2 汇编版 原子操作 CAS

基本原理说明 在 x86 和 ARM 架构上&#xff0c;原子操作通常利用硬件提供的原子指令来实现&#xff0c;比如 LOCK 前缀&#xff08;x86&#xff09;或 LDREX/STREX&#xff08;ARM&#xff09;。以下是一些关键的原子操作&#xff08;例如原子递增和比较交换&#xff09;的汇…...

关于llama2:从原始llama-2-7b到llama-2-7b-hf的权重转换教程

1.首先&#xff0c;我是从各个教程里面选了一个实际操作的教程&#xff08;这样更加靠谱&#xff09;&#xff1a;下载llama2-7b并转hf模型_huggingface 下载llama2-7b-chat-hf-CSDN博客 2.但是&#xff0c;其实我在另外一篇更好的教程里面看到过一个坑&#xff08;这篇好像是腾…...

物理机内网穿透

前言&#xff1a; 本文主要讲述如何使用内网穿透以及其安全性。 将带领大家在公网上搭建几个常用靶场。 一&#xff0c;什么是内网穿透。 大多数情况下&#xff0c;我们的个人电脑都处于内网&#xff0c;即没有可公开访问的独立 IP 地址&#xff0c;因此其他内网用户找不到…...

构建一个rust生产应用读书笔记四(实战1)

我们需要从访客那里收集哪些信息&#xff0c;以便将其登记为电子邮件通讯的订阅者&#xff1f; 电子邮件地址&#xff1a;这是最基本的要求&#xff0c;因为我们需要通过电子邮件地址向订阅者发送内容。姓名&#xff1a;虽然这不是强制性的&#xff0c;但我们希望收集一个名字…...

[LeetCode-Python版]206. 反转链表(迭代+递归两种解法)

题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3&#xff1…...

shardingsphere分库分表跨库访问 添加分片规则

shardingsphere分库分表跨库访问 添加分片规则 建立 JDBC 环境 创建表 t_order&#xff1a; CREATE TABLE t_order (tid bigint(20) NOT NULL,tname varchar(255) DEFAULT NULL,goods_id bigint(20) DEFAULT NULL,tstatus varchar(255) DEFAULT NULL,PRIMARY KEY (tid) ) E…...

【NLP 15、深度学习处理文本】

目录 一、反向传播 ​编辑 1.反向传播运算过程 2.前向传播和反向传播的作用 前向传播 反向传播 3.定义模型&#xff08;torch包&#xff09; 4.手动实现 ① 线性层 ② sigmoid激活函数 ③ 手动实现MSE均方差损失函数 ④ 前向传播 ⑤ 手动实现梯度计算 ⑤ 权重的更新&#xff1a…...

Android Studio创建新项目并引入第三方so外部aar库驱动NFC读写器读写IC卡

本示例使用设备&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bbW3AUC&ftt&id615391857885 一、打开Android Studio,点击 File> New>New project 菜单&#xff0c;选择 要创建的项目模版&#xff0c;点击 Next 二、输入项目名称…...

3D视觉[一]3D计算机视觉

3D视觉[一]3D计算机视觉 3D计算机视觉概述 像机标定 文章目录 3D视觉[一]3D计算机视觉前言一、人类视觉二、计算机视觉2.1 计算机视觉的研究目的2.2 计算机视觉的研究任务2.3 计算机视觉的研究方法2.4 视觉计算理论2.5 马尔框架中计算机视觉表达的四个层次2.5.1 图像&#xff…...

Linux权限(超详细彻底搞懂Linux的权限)

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a;Linux常见指令(初学者必看) &#x1f516;流水不争&#xff0c;争的是滔滔不 一、Linux下的两种用户超级用户&…...

Ubuntu22.04安装docker desktop遇到的bug

1. 确认已启用 KVM 虚拟化 如果加载了模块&#xff0c;输出应该如下图。说明 Intel CPU 的 KVM 模块已开启。 否则在VMware开启宿主机虚拟化功能&#xff1a; 2. 下一步操作&#xff1a; Ubuntu | Docker Docs 3. 启动Docker桌面后发现账户登陆不上去&#xff1a; Sign in | …...

网新恒天八股总结

Java的基本数据类型 四类八种 整数类型&#xff1a;byte,short,int,long 浮点类型&#xff1a;float,double 字符类型&#xff1a;char 布尔类型&#xff1a;boolean char类型的范围 0 ~ 65535&#xff0c;可以表示16位无符号整数 equals和的区别 &&#xff0c;&&a…...

【AIGC】与模型对话:理解与预防ChatGPT中的常见误解

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;模型的工作原理和用户期望差异人工智能模型的基本工作原理认知上的局限与误解用户期望与模型实际能力的差距精确理解用户意图的重要性实际应用中的建议 &…...

09篇--图片的水印添加(掩膜的运用)

如何添加水印&#xff1f; 添加水印其实可以理解为将一张图片中的某个物体或者图案提取出来&#xff0c;然后叠加到另一张图片上。具体的操作思想是通过将原始图片转换成灰度图&#xff0c;并进行二值化处理&#xff0c;去除背景部分&#xff0c;得到一个类似掩膜的图像。然后…...

Qt 使用modbus协议

Qt 框架下 使用modbus协议 一&#xff0c;使用Qt原生的 QModbusClient &#xff0c;比如QModbusTcpClient 1&#xff0c;因为modbus的读写 需要在同一个线程中&#xff0c;所以需要在主线程中利用moveToThread的方式&#xff0c;将业务逻辑封装到 子线程中。 2&#xff0c;m…...

pip离线安装一个github仓库

要使用pip安装一个本地Git仓库&#xff0c;你可以按照以下步骤操作&#xff1a; 确保你已经克隆了Git仓库到本地。 进入仓库所在的目录。 使用pip安装。 以下是具体的命令&#xff1a; 克隆Git仓库到本地&#xff08;替换下面的URL为你的仓库URL&#xff09; git clone https…...

【ETCD】【源码阅读】深入分析 storeTxnWrite.Put方法源码

该方法是 storeTxnWrite 类型中的核心方法&#xff0c;负责将键值对存储到数据库&#xff0c;同时处理键的元数据&#xff08;如版本、修订号、租约&#xff09;并管理租约关联。 目录 一、完整代码二、方法详解方法签名1. 计算修订号并初始化变量2. 检查键是否已存在3. 生成索…...

桥接模式的理解和实践

桥接模式&#xff08;Bridge Pattern&#xff09;&#xff0c;又称桥梁模式&#xff0c;是一种结构型设计模式。它的核心思想是将抽象部分与实现部分分离&#xff0c;使它们可以独立地进行变化&#xff0c;从而提高系统的灵活性和可扩展性。本文将详细介绍桥接模式的概念、原理…...

【Rust自学】3.2. 数据类型:标量类型

3.2.0. 写在正文之前 欢迎来到Rust自学的第三章&#xff0c;一共有6个小节&#xff0c;分别是: 变量与可变性数据类型&#xff1a;标量类型&#xff08;本文&#xff09;数据类型&#xff1a;复合类型函数和注释控制流&#xff1a;if else控制流&#xff1a;循环 通过第二章…...

【Leetcode Top 100】199. 二叉树的右视图

问题背景 给定一个二叉树的 根节点 r o o t root root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 数据约束 二叉树的节点个数的范围是 [ 0 , 100 ] [0,100] [0,100] − 100 ≤ N o d e . v a l ≤ 100…...

Java并发编程框架之其他并发工具

选错了就选错了&#xff0c;不要一遍一遍的后悔&#xff0c;总是一遍遍的想&#xff0c;当时怎么样就好了&#xff0c;不要欺负当时的自己&#xff0c;当时你一个人站在迷雾中&#xff0c;也很迷茫&#xff0c;就算重新来一遍&#xff0c;以你当时的阅历和心智&#xff0c;还是…...

MinerU:PDF文档提取工具

目录 docker一键启动本地配置下载模型权重文件demo.py使用命令行启动GPU使用情况 wget https://github.com/opendatalab/MinerU/raw/master/Dockerfile docker build -t mineru:latest .docker一键启动 有点问题&#xff0c;晚点更新 本地配置 就是在Python环境中配置依赖和…...

Unity性能优化---使用SpriteAtlas创建图集进行批次优化

在日常游戏开发中&#xff0c;UI是不可缺少的模块&#xff0c;而在UI中又使用着大量的图片&#xff0c;特别是2D游戏还有很多精灵图片存在&#xff0c;如果不加以处理&#xff0c;会导致很高的Batches&#xff0c;影响性能。 比如如下的例子&#xff1a; Batches是9&#xff0…...

wazuh-modules-sca-scan

sca模块主函数wm_sca_main -> wm_sca_start 检查policy文件中的每一个项目wm_sca_check_policy static int wm_sca_check_policy(const cJSON * const policy, const cJSON * const checks, OSHash *global_check_list) {if(!policy) {return 1;}const cJSON * const id c…...

力扣-图论-15【算法学习day.65】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非…...

JS萤石云录像回放拖动进度条无法正常播放

问题描述&#xff1a; 本项目版本&#xff1a;vue2.6.12&#xff0c;webpack3.6.0&#xff0c;ezuikit-js0.7.2 在使用萤石云的JavaScript SDK做监控的直播、录像回放时&#xff0c;遇到部分设备的录像回放&#xff0c;无法根据控制面板的拖动进度条查看某时间段的录像。 官方…...

Spring Boot 启动时间优化全攻略

引言 随着 Spring Boot 的广泛应用&#xff0c;开发者享受到了快速开发和自动化配置的便利。然而&#xff0c;随着项目复杂度的增加&#xff0c;Spring Boot 项目启动时间也变得越来越长&#xff0c;这在开发、调试和部署阶段可能会成为效率瓶颈。如何优化 Spring Boot 的启动…...

ubuntu服务器木马类挖矿程序排查、及安全管理总结

版本 24.04 由于GPU多卡服务器多人使用&#xff0c;需要链接隧道ssh等&#xff0c;容易中招挖矿脚本。 总的思路是&#xff0c;顺着进程的PID回溯最终的程序运行起点&#xff0c;这里可以先看一下日志&#xff1a; journalctl -u PID 通过 PID 精确定位进程的信息&#xff0c…...

redis 使用Lettuce 当redis挂掉重启之后 网络是怎么重新连接

Lettuce是一个高性能的Java Redis客户端&#xff0c;支持同步、异步和反应式编程模式 Lettuce的核心功能包括&#xff1a; ‌高性能‌&#xff1a;通过使用Netty作为底层网络通信框架&#xff0c;实现了非阻塞IO&#xff0c;提高了性能。‌丰富的API‌&#xff1a;提供了丰富…...

【PyTorch】实现在训练过程中自定义动态调整学习率

问题描述&#xff1a; 在使用 PyTorch 训练自定义神经网络时&#xff0c;我们希望能够动态地调整学习率&#xff0c;以便在训练过程中逐渐优化模型&#xff0c;避免过拟合并加速收敛。那么&#xff0c;如何在 PyTorch 中实现这一功能呢&#xff1f; 解决方案&#xff1a; 在训…...

【Flink-scala】DataStream编程模型总结

系列文章目录 1.【Flink-Scala】DataStream编程模型之数据源、数据转换、数据输出 2.【Flink-scala】DataStream编程模型之 窗口的划分-时间概念-窗口计算程序 3.【Flink-scala】DataStream编程模型之窗口计算-触发器-驱逐器 4.【Flink-scala】DataStream编程模型之水位线 5.【…...

语音芯片赋能可穿戴设备:开启个性化音频新体验

在科技日新月异的今天&#xff0c;语音芯片与可穿戴设备的携手合作&#xff0c;正引领我们步入一个前所未有的个性化音频时代。这一创新融合&#xff0c;用户可以享受到更加个性化、沉浸式的音频体验。下面将详细介绍语音芯片与可穿戴设备合作的优点和具体应用。 1. 定制化音效…...

JavaFX使用jfoenix的UI控件

jfoenix还是一个不错的样式&#xff0c;推荐使用&#xff0c;而且也可以支持scene builder中的拖拖拽拽 需要注意的是过高的javafx版本可能会使得某些样式或控件无法使用 比如alert控件&#xff0c;亲测javaFX 19版本可以正常使用 1.在pom.xml中引入依赖 GitHub地址https://gi…...

SpringBoot集成ENC对配置文件进行加密

在线MD5生成工具 配置文件加密&#xff0c;集成ENC 引入POM依赖 <!-- ENC配置文件加密 --><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>2.1.2</ver…...

基于AI对话生成剧情AVG游戏

游戏开发这个领域&#xff0c;一直有较高的学习门槛。作为一个非专业的游戏爱好者&#xff0c;如果想要开发游戏&#xff0c;往往受制于游戏引擎的专业程度&#xff0c;难以完成复杂的游戏项目。 AI IDE的诞生&#xff0c;提供了另外的一种思路&#xff0c;即通过AI 生成项目及…...

MAVEN--Maven的生命周期,pom.xml详解,Maven的高级特性(模块化、聚合、依赖管理)

目录 &#xff08;一&#xff09;Maven的生命周期 1.Maven的三套生命周期 2.Maven常用命令 &#xff08;二&#xff09;pom.xml详解 &#xff08;三&#xff09;Maven的高级特性&#xff08;模块化、聚合、依赖管理&#xff09; 1.Maven的依赖范围 2.版本维护 3.依赖传…...

SpringBoot的事务钩子函数

如果需要在A方法执行完成之后做一个不影响主方法运行的动作B&#xff0c;我们需要判断这个A方法是否存在事务&#xff0c;并且使用异步执行动作B&#xff1b; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transa…...

uniapp滚动消息列表

两个相同的循环列表&#xff0c;循环滚动 <view class"winners_list uni-flex uni-column" :animation"animationData"><view v-for"(item, index) in winnersList" :key"index" class"li uni-flex uni-column"&g…...

基于python对pdf文件进行加密等操作

利用python对pdf文件进行操作 读取pdf-源码 import PyPDF2 # 读取pdf格式的文件 reader PyPDF2.PdfFileReader(示例文件/aaa.pdf) print(reader)# 读取指定页面的文件 page reader.getPage(0) # 输出当前页面的文本数据 print(page.extractText())读取pdf-源码解析 这段代…...

Three.js材质纹理扩散过渡

Three.js材质纹理扩散过渡 import * as THREE from "three"; import { ThreeHelper } from "/src/ThreeHelper"; import { LoadGLTF, MethodBaseSceneSet } from "/src/ThreeHelper/decorators"; import { MainScreen } from "/src/compone…...

【Leetcode 每日一题 - 扩展】45. 跳跃游戏 II

问题背景 给定一个长度为 n n n 的 0 0 0 索引 整数数组 n u m s nums nums。初始位置为 n u m s [ 0 ] nums[0] nums[0]。 每个元素 n u m s [ i ] nums[i] nums[i] 表示从索引 i i i 向前跳转的最大长度。换句话说&#xff0c;如果你在 n u m s [ i ] nums[i] nums[i…...

被裁20240927 --- YOLO 算法

背景 在云端部署ViSP&#xff0c;ViSP实现视觉伺服、yolo实现视觉跟踪。 开源的2d视觉跟踪算法有哪些&#xff1f; 开源的2D视觉跟踪算法有很多呢&#xff0c;这里给你推荐一些比较知名和常用的吧。 ByteTrackV2&#xff1a;这是一个通用2D跟踪算法&#xff0c;提出了分层的…...

AI技术架构:从基础设施到应用

人工智能&#xff08;AI&#xff09;的发展&#xff0c;正以前所未有的速度重塑我们的世界。了解AI技术架构&#xff0c;不仅能帮助我们看懂 AI 的底层逻辑&#xff0c;还能掌握其对各行业变革的潜力与方向。 一、基础设施层&#xff1a;AI 技术的坚实地基 基础设施层是 AI 技…...

植物大战僵尸辅助【控制台版本】

前面介绍了使用CE和OD的简单使用&#xff1a;CE和OD介绍和使用CE查找阳光的教学&#xff1a;阳光基地址和偏移地址&#xff0c;下面先使用最简单的控制台程序来实现修改阳光的功能。 项目地址 1.分析程序 我们的控制台程序想要修改植物大战僵尸游戏内的数据&#xff0c;它们…...

css中样式前加 css样式前面加个圆点

创建CSS样式,样式名称的前面需要加什么 1、我们只知道符号代表的意思是at&#xff0c;其翻译是 在... 例如media就是 在媒介上。没人规定本身具有什么意义&#xff0c;或者说就算规定了我们也改变不了&#xff0c;只需要知道其规定属性的用法即可。 2、px;}然后根据你自己索要…...

算法刷题Day18: BM41 输出二叉树的右视图

题目链接 描述 思路&#xff1a; 递归构造二叉树在Day15有讲到。复习一下&#xff0c;就是使用递归构建左右子树。将中序和前序一分为二。 接下来是找出每一层的最右边的节点&#xff0c;可以利用队列层次遍历。 利用队列长度记录当前层有多少个节点&#xff0c;每次从队列里…...

如何实现规范化LabVIEW编程

规范编写LabVIEW程序的目的是提高代码的可读性、可维护性、可扩展性&#xff0c;并确保团队成员能够高效地理解和修改代码。以下是一些关键建议&#xff0c;帮助您编写更专业的LabVIEW代码&#xff0c;并确保它易于后续的升级和维护&#xff1a; ​ 1. 合理的项目结构 目录结构…...

TQ15EG开发板教程:使用SSH登录petalinux

本例程在上一章“创建运行petalinux2019.1”基础上进行&#xff0c;本例程将实现使用SSH登录petalinux。 将上一章生成的BOOT.BIN与imag.ub文件放入到SD卡中启动。给开发板插入电源与串口&#xff0c;注意串口插入后会识别出两个串口号&#xff0c;都需要打开&#xff0c;查看串…...

Springboot+vue实现大文件上传

背景&#xff1a;为了实现大文件上传的功能 1新建数据表sql file_chunk CREATE TABLE file_chunk (id bigint UNSIGNED NOT NULL AUTO_INCREMENT,file_name varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NULL DEFAULT NULL COMMENT 文件名,chunk_nu…...

Linux笔记

常用的基本命令 查询某个安装包有没有安装某个软件 使用的命令是rpm -qa |grep 软件名字 卸载软件 rpm -e --nodeps 软件名称 查看已经启动的服务 netstat -tunlp 一般我们在Linux系统中上传文件一般上传到 /usr/local/src的目录下 查看防火墙的命令 firewall-cmd --sta…...