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

【ELF2学习板】OpenCL程序测试

目录

引言

OpenCL简介

主要特点

编程模型

应用场景

测试程序

代码说明

构建编译环境

头文件

库文件

程序编译

测试结果

结语


引言

ELF2开发板采用的是RK3588处理器,它是瑞芯微推出的一款高性能 SoC。RK3588 集成了 ARM Mali-G610 MP4 GPU,这款 GPU 具备强大的并行计算能力。要充分发挥GPU的计算能力,可以使用 OpenCL库。OpenCL(Open Computing Language)是一个开放的、跨平台的并行编程标准,用于编写可在多种计算设备(如 CPU、GPU、FPGA 等)上运行的并行程序。瑞芯微为 RK3588 提供专门的 GPU 驱动,支持 OpenCL 标准。

OpenCL简介

主要特点

  • 跨平台性:OpenCL 可以在不同厂商的硬件设备上运行,包括英特尔、AMD、英伟达等公司生产的 CPU 和 GPU,以及其他类型的加速器,如 FPGA。这使得开发者能够编写一次代码,然后在多种设备上部署和运行。
  • 并行计算能力:它允许开发者充分利用计算设备中的大量计算核心,通过并行计算来加速程序的执行。对于大规模数据处理、科学计算、图形处理等领域,OpenCL 可以显著提高程序的性能。
  • 灵活性:OpenCL 提供了丰富的编程模型,开发者可以根据具体的应用场景和硬件特性,灵活地控制并行计算的粒度和方式。可以通过调整工作组大小、全局工作大小等参数来优化程序性能。

编程模型

OpenCL 的编程模型主要涉及以下几个关键概念:

  • 平台(Platform):代表一个 OpenCL 实现的集合,通常对应于一个硬件厂商的软件栈。例如,英特尔的 OpenCL 平台、英伟达的 OpenCL 平台等。
  • 设备(Device):指具体的计算设备,如 CPU、GPU 或 FPGA。一个平台可以包含多个设备。
  • 上下文(Context):是 OpenCL 运行时的一个环境,它管理着所有的 OpenCL 对象,如内存对象、程序对象、内核对象等。
  • 命令队列(Command Queue):用于向设备发送命令,如内核执行命令、内存读写命令等。命令队列可以是有序的或无序的,开发者可以根据需要选择不同的队列类型。
  • 内核(Kernel):是 OpenCL 中并行执行的基本单元,它是一段用 OpenCL C 语言编写的函数,在设备上并行执行。
  • 内存对象(Memory Object):用于在主机和设备之间传输数据,包括缓冲区(Buffer)和图像(Image)两种类型。

应用场景

  • 科学计算:在气象预报、分子动力学模拟、金融建模等领域,需要处理大量的数据和复杂的计算任务。OpenCL 可以利用 GPU 等设备的并行计算能力,加速这些计算任务的执行。
  • 图形处理:虽然 OpenGL 和 DirectX 是专门用于图形渲染的 API,但 OpenCL 可以用于图形处理中的一些辅助计算任务,如物理模拟、图像处理等。
  • 数据挖掘和机器学习:在处理大规模数据集时,OpenCL 可以加速数据挖掘算法和机器学习模型的训练过程。例如,加速神经网络的前向传播和反向传播计算。

测试程序

以下是用豆包生成的一个简单的 OpenCL 测试程序,该程序会对两个数组进行加法运算。此程序既可以验证功能的正确性,也能通过计时来体现性能提升的能力。

#include <stdio.h>
#include <stdlib.h>
#include <CL/cl.h>
#include <time.h>#define ARRAY_SIZE 1048576 // 增大数据规模// OpenCL 内核代码
const char *kernelSource ="__kernel void vector_add(__global const float *a, __global const float *b, __global float *c) {\n""    int i = get_global_id(0);\n""    c[i] = a[i] + b[i];\n""}\n";// CPU 上的数组加法函数
void cpu_vector_add(float *a, float *b, float *c, int size) {for (int i = 0; i < size; i++) {c[i] = a[i] + b[i];}
}int main() {cl_platform_id platform_id = NULL;cl_device_id device_id = NULL;cl_uint ret_num_devices;cl_uint ret_num_platforms;cl_int ret;// 获取平台信息ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);if (ret != CL_SUCCESS) {printf("Error: Failed to get platform IDs!\n");return -1;}// 获取设备信息ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device_id, &ret_num_devices);if (ret == CL_DEVICE_NOT_FOUND) {ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_CPU, 1, &device_id, &ret_num_devices);}if (ret != CL_SUCCESS) {printf("Error: Failed to get device IDs!\n");return -1;}// 创建上下文cl_context context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);if (ret != CL_SUCCESS) {printf("Error: Failed to create context!\n");return -1;}// 创建命令队列cl_command_queue command_queue = clCreateCommandQueue(context, device_id, 0, &ret);if (ret != CL_SUCCESS) {printf("Error: Failed to create command queue!\n");return -1;}// 创建内存对象float *a = (float *)malloc(ARRAY_SIZE * sizeof(float));float *b = (float *)malloc(ARRAY_SIZE * sizeof(float));float *c_gpu = (float *)malloc(ARRAY_SIZE * sizeof(float));float *c_cpu = (float *)malloc(ARRAY_SIZE * sizeof(float));for (int i = 0; i < ARRAY_SIZE; i++) {a[i] = (float)i;b[i] = (float)(i * 2);}cl_mem a_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, ARRAY_SIZE * sizeof(float), NULL, &ret);cl_mem b_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, ARRAY_SIZE * sizeof(float), NULL, &ret);cl_mem c_mem_obj = clCreateBuffer(context, CL_MEM_WRITE_ONLY, ARRAY_SIZE * sizeof(float), NULL, &ret);if (ret != CL_SUCCESS) {printf("Error: Failed to create memory objects!\n");return -1;}// 将数据写入内存对象ret = clEnqueueWriteBuffer(command_queue, a_mem_obj, CL_TRUE, 0, ARRAY_SIZE * sizeof(float), a, 0, NULL, NULL);ret |= clEnqueueWriteBuffer(command_queue, b_mem_obj, CL_TRUE, 0, ARRAY_SIZE * sizeof(float), b, 0, NULL, NULL);if (ret != CL_SUCCESS) {printf("Error: Failed to write data to memory objects!\n");return -1;}// 创建程序对象cl_program program = clCreateProgramWithSource(context, 1, (const char **)&kernelSource, NULL, &ret);if (ret != CL_SUCCESS) {printf("Error: Failed to create program object!\n");return -1;}// 构建程序ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);if (ret != CL_SUCCESS) {size_t len;char buffer[2048];clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);printf("Error: Failed to build program:\n%s\n", buffer);return -1;}// 创建内核对象cl_kernel kernel = clCreateKernel(program, "vector_add", &ret);if (ret != CL_SUCCESS) {printf("Error: Failed to create kernel object!\n");return -1;}// 设置内核参数ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&a_mem_obj);ret |= clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&b_mem_obj);ret |= clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&c_mem_obj);if (ret != CL_SUCCESS) {printf("Error: Failed to set kernel arguments!\n");return -1;}// 测量 GPU 执行时间clock_t start_gpu = clock();// 执行内核size_t global_item_size = ARRAY_SIZE;size_t local_item_size = 256; // 调整本地工作组大小ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);if (ret != CL_SUCCESS) {printf("Error: Failed to enqueue kernel!\n");return -1;}// 读取结果ret = clEnqueueReadBuffer(command_queue, c_mem_obj, CL_TRUE, 0, ARRAY_SIZE * sizeof(float), c_gpu, 0, NULL, NULL);if (ret != CL_SUCCESS) {printf("Error: Failed to read result!\n");return -1;}clock_t end_gpu = clock();double time_gpu = ((double)(end_gpu - start_gpu)) / CLOCKS_PER_SEC;// 测量 CPU 执行时间clock_t start_cpu = clock();cpu_vector_add(a, b, c_cpu, ARRAY_SIZE);clock_t end_cpu = clock();double time_cpu = ((double)(end_cpu - start_cpu)) / CLOCKS_PER_SEC;// 验证结果int correct = 1;for (int i = 0; i < ARRAY_SIZE; i++) {if (c_gpu[i] != c_cpu[i]) {correct = 0;break;}}if (correct) {printf("Results are correct!\n");} else {printf("Results are incorrect!\n");}// 输出性能对比结果printf("CPU execution time: %f seconds\n", time_cpu);printf("GPU execution time: %f seconds\n", time_gpu);if (time_gpu < time_cpu) {printf("GPU is %.2f times faster than CPU.\n", time_cpu / time_gpu);} else {printf("CPU is %.2f times faster than GPU.\n", time_gpu / time_cpu);}// 释放资源ret = clFlush(command_queue);ret = clFinish(command_queue);ret = clReleaseKernel(kernel);ret = clReleaseProgram(program);ret = clReleaseMemObject(a_mem_obj);ret = clReleaseMemObject(b_mem_obj);ret = clReleaseMemObject(c_mem_obj);ret = clReleaseCommandQueue(command_queue);ret = clReleaseContext(context);free(a);free(b);free(c_gpu);free(c_cpu);return 0;
}    

代码说明

  1. 平台与设备信息获取:借助 clGetPlatformIDs 和 clGetDeviceIDs 来获取可用的 OpenCL 平台与设备。
  2. 上下文与命令队列创建:运用 clCreateContext 创建上下文,使用 clCreateCommandQueue 创建命令队列。
  3. 内存对象创建:通过 clCreateBuffer 创建内存对象,并且使用 clEnqueueWriteBuffer 把数据写入这些对象。
  4. 程序与内核创建:利用 clCreateProgramWithSource 创建程序对象,通过 clBuildProgram 构建程序,使用 clCreateKernel 创建内核对象。
  5. 内核参数设置与执行:使用 clSetKernelArg 设置内核参数,通过 clEnqueueNDRangeKernel 执行内核。
  6. 结果读取与验证:使用 clEnqueueReadBuffer 读取结果,然后验证计算结果的正确性。
  7. 资源释放:释放所有创建的 OpenCL 对象和分配的内存。

要充分发挥 GPU 的性能优势,需要增大数据规模,确保 GPU 处于良好的工作状态。

构建编译环境

如果使用的是Ubuntu桌面板,可以直接在ELF2开发板上进行本地编译。

对于Buildroot版本,正常的ELF2编译环境的构建应该基于厂商提供的SDK或者Linux系统源码。不过我偷了个懒,直接从OpenCL的官网下载了头文件,从开发板上拷贝出来所需要的库文件,搭建了一个简易的编译环境。

头文件

从GitHub - KhronosGroup/OpenCL-Headers at v2020.03.13下载需要的头文件,并保存在OpenCL-Headers-2020.03.13目录下。

库文件

把开发板上的/usr/lib/libmali.so.1.9.0文件拷贝到PC上,改名为libmali.so,放置在lib目录下。RK3588的OpenCL库文件就是这个libmali。

程序编译

建立一个src目录,将程序保存在该目录下,然后用如下命令进行编译:

aarch64-linux-gnu-gcc opencl_array_addition.c -o opencl_array_addition -lmali -I../OpenCL-Headers-2020.03.13 -L../lib/  -Wl,--allow-shlib-undefined

这里使用-Wl,--allow-shlib-undefined选项,忽略所有找不到函数的链接错误。因为Mali库还需要其他一些库的支持。

测试结果

程序运行的结果如下:

root@elf2-buildroot:~# ./opencl_array_addition
arm_release_ver: g13p0-01eac0, rk_so_ver: 10
Results are correct!
CPU execution time: 0.022247 seconds
GPU execution time: 0.006805 seconds
GPU is 3.27 times faster than CPU.

从这个结果可以看出,在数据量很大的情况下,GPU还是发挥出来其自身的并行优势的。 

结语

初步的测试结果表明,OpenCL可以利用RK3588的GPU进行并行计算。后面会尝试更复杂的例子。

相关文章:

【ELF2学习板】OpenCL程序测试

目录 引言 OpenCL简介 主要特点 编程模型 应用场景 测试程序 代码说明 构建编译环境 头文件 库文件 程序编译 测试结果 结语 引言 ELF2开发板采用的是RK3588处理器&#xff0c;它是瑞芯微推出的一款高性能 SoC。RK3588 集成了 ARM Mali-G610 MP4 GPU&#xff0c;…...

EtherCAT转ProfiNet边缘计算网关配置优化:汽车制造场景下PLC与机器人协同作业案例

1.行业背景与需求分析 智能汽车焊装车间是汽车制造的核心工艺环节&#xff0c;某德国豪华品牌在其上海MEB工厂新建的焊装车间中&#xff0c;采用西门子S7-1500PLC作为ProfiNet主站&#xff0c;负责整线协调与质量追溯&#xff1b;同时部署KUKAKR1500Titan机器人&#xff08;Eth…...

AI 推理与训练优化的核心理论体系建构及关键技术分析框架

AI 推理与训练优化的核心理论体系建构及关键技术分析框架 一、推理加速的动态系统理论建模与算法设计 &#xff08;一&#xff09;基于MDP的动态计算图理论 生物启发的决策框架&#xff1a;模拟灵长类视觉系统的注意力分配机制&#xff0c;构建马尔可夫决策过程&#xff08;M…...

Jupyter 中 Markdown 邂逅 LaTeX:一场知识的绮梦

引言&#xff1a; 在日常编程和数据分析工作中&#xff0c;我们经常需要记录和分享信息。传统的注释方式功能有限&#xff0c;而富文本编辑器又过于臃肿。Markdown作为一种轻量级标记语言&#xff0c;完美解决了这个问题。 为什么选择Markdown&#xff1f; Markdown具有两大优势…...

AI 对话高效输入指令攻略(二):关于豆包的指令

免责声明&#xff1a;该文章的所有样例只是测试&#xff0c;没有唆使大家利用AI抄袭作业&#xff01;更没有宣传豆包。 前言 没有听不懂话的AI&#xff0c;只有不会调教AI的人。&#xff08;自己瞎说的&#xff09;当你把AI当人看之后&#xff0c;你就会发现&#xff0c;他是多…...

Apache Atlas构建安装(Linux)

一、环境准备 maven 3.6.3python 2.7nodejs 12java 1.8 注意环境一定要对&#xff0c;不然一堆问题 1. python2.7 安装 参考文章&#xff1a;https://blog.csdn.net/weixin_42081389/article/details/101276251 打开链接&#xff1a;https://www.python.org/downloads/sourc…...

【JAVA】在idea新加artifact时,点击Build-Build Artifacts时,新加的artifact不能选中

首先保证添加artifact无问题&#xff0c;比如依赖都正确、无重复命令的情况等 办法 一 File > Invalidate Caches / Restart。 重启IDEA后&#xff0c;重新检查Artifact是否可选 办法 二 打开 Project Structure&#xff08;CtrlShiftAltS&#xff09;。 进入 Artifacts 选…...

【杂谈】-自动驾驶变革:货运革新与机器人出租车崛起

自动驾驶变革&#xff1a;货运革新与机器人出租车崛起 文章目录 自动驾驶变革&#xff1a;货运革新与机器人出租车崛起一、市场主导力量二、机器人出租车的崛起三、货运运输的变革四、商业视角下的分析五、责任归属问题 汽车行业&#xff0c;凭借其在道路状况、车辆性能及整体环…...

吊顶上的灯线怎么预留?是提前到位还是后期随意拉拽?

业主问家里的灯线怎么预留&#xff1f; 问业主灯线指的是主灯还是射灯&#xff1f; 业主说他家里边要做边吊&#xff0c;边吊上边要放一些射灯。 在射灯上方对应的留灯线就可以&#xff0c;不用特别的精确&#xff0c;把线头放的稍微长一点即可。 这位业主又说为什么要这样预留…...

网易游戏 x Apache Doris:湖仓一体架构演进之路

导读&#xff1a;网易游戏引入 Apache Doris 升级架构&#xff0c;先是替换 Elasticsearch、Hbase、Clickhouse 构建了实时数仓&#xff0c;而后基于 Apache Doris 和 Iceberg 构建了湖仓融合架构&#xff0c;实现架构的大幅简化及统一。目前&#xff0c;网易游戏 Apache Doris…...

大模型会不会取代人类工作

大模型是否会取代人类工作&#xff1f; 随着人工智能技术的迅猛发展&#xff0c;尤其是大型语言模型&#xff08;如GPT-4、BERT等&#xff09;的出现&#xff0c;人们开始担忧这些先进的技术是否会在未来取代人类的工作。这种担忧并非空穴来风&#xff0c;历史上每一次技术革命…...

深入理解 Linux 权限管理:从 Shell 到文件权限

&#x1f33c;&#x1f33c; 在 Linux 系统中&#xff0c;权限是保障系统安全与稳定的核心之一。每个操作都可能涉及权限的管理和控制&#xff0c;特别是当你开始以不同用户的身份进行操作时。本文将通过生动的比喻与详细的技术解析&#xff0c;带你一起深入理解 Linux 权限系统…...

.net core 项目快速接入Coze智能体-开箱即用-全局说明

目录 一、Coze智能体的核心价值 二、开箱即用-效果如下 三 流程与交互设计 为什么要分析意图&#xff0c;而不是全部交由AI处理。 四 接入前的准备工作 五&#xff1a;代码实现----字节Coze 签署 JWT和获取Token .net core 项目快速接入Coze智能体-开箱即用 .net core快…...

React 开放封闭原则详解,构建可扩展的应用

开放封闭原则 React 采用了一些面向对象编程的原则和概念&#xff0c;其中之一就是开放封闭原则&#xff08;Open-Closed Principle&#xff0c;OCP&#xff09;&#xff0c;它是面向对象编程的一个基本原则。本文将详细解释开放封闭原则的概念和在 React 中的应用&#xff0c;…...

【并行分布计算】Hadoop完全分布搭建

Hadoop完全分布搭建 1.为了使机器都处于同一个局域网中&#xff0c;先要修改机器的ip地址分配方式为固定ip&#xff0c;并为其固定分配一个ip地址。 [rootlocalhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33 问题&#xff1a;修改ip地址后&#xff0c;网络无法正常…...

Three.js + React 实战系列 : 从零搭建 3D 个人主页

可能你对tailiwindcss毫不了解&#xff0c;别紧张&#xff0c;记住我们只是在学习&#xff0c;学习的是作者的思想和技巧&#xff0c;并不是某一行代码。 在之前的几篇文章中&#xff0c;我们已经熟悉了 Three.js 的基本用法&#xff0c;并通过 react-three-fiber 快速构建了一…...

四月十六日华为发布会

智能家居及穿戴类 华为智能门锁 2 系列发布&#xff1a;2025 年 4 月 16 日&#xff0c;华为智能门锁 2 系列正式发布。该系列引入 AI 掌静脉识别技术和 AI 3D 人脸识别 3.0&#xff0c;具备高安全性&#xff1b;采用超清智能大猫眼&#xff0c;可视范围达 161&#xff1b;通过…...

23种设计模式-创建型模式之工厂方法模式(Java版本)

Java 工厂方法模式&#xff08;Factory Method Pattern&#xff09;详解 &#x1f31f; 什么是工厂方法模式&#xff1f; 工厂方法模式是一种创建型设计模式&#xff0c;定义一个创建对象的接口&#xff0c;让子类决定实例化哪一个类。 它让类的实例化推迟到子类进行&#xf…...

基于FreeBSD的Unix系统搭建Nginx+PHP5运行环境

服务器操作系统版本&#xff1a;FreeBSD-10.1-i386 Nginx安装配置 1.以ports形式安装 #进入nginx目录 cd /usr/ports/www/nginx #执行编译安装 make install 2.编辑配置文件 #进入etc目录 cd /etc #编辑配置文件 ee rc.conf #进入编辑模式 i #参照如下设置 nginx_enable”YES…...

医院处方外流对接外部药房系统(合规python代码版)

系统概述 本系统旨在帮助医院实现与外部零售药店的安全、合规对接,满足2025年医保局和卫健委关于处方流转的最新规定。系统采用Python开发,基于RESTful API实现医院HIS系统与外部药房之间的处方信息传输、医保支付验证和处方状态跟踪等功能。 系统架构 #mermaid-svg-zKU5Wj…...

第十七届“华中杯”B 题校园共享单车的调度与维护问题分析

问题1&#xff1a;估算共享单车总量及不同停车点位在不同时间点的数量分布 首先&#xff0c;我们需要对附件1的数据进行汇总&#xff0c;以估算出校园内的共享单车总量。由于数据是按不同时间和停车点位统计的&#xff0c;我们可以通过对所有时间和点位的单车数量进行求和&…...

线程池的封装(c/c++)

前言&#xff1a;本文将要封装的线程池相关接口是基于之前一篇文章中的实现&#xff08;文章链接&#xff1a;Linux多线程编程的艺术&#xff1a;封装线程、锁、条件变量和信号量的工程实践-CSDN博客&#xff09;。不过无需担心&#xff0c;即使您没有阅读过前文&#xff0c;只…...

「数据可视化 D3系列」入门第六章:比例尺的使用

比例尺的使用 一、比例尺是什么&#xff1f;典型示例&#xff1a; 二、常用比例尺类型1. 线性比例尺 (scaleLinear)2. 序数比例尺 (scaleOrdinal)3. 其他常用比例尺类型&#xff1a; 三、实际应用主要改进点说明 四、比例尺的高级用法1. 颜色比例尺2. 时间比例尺3. 分段比例尺 …...

巧用ChatGPT生成适合小白的Python练习题,助力编程入门

&#x1f381;个人主页&#xff1a;User_芊芊君子 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 &#x1f50d;系列专栏&#xff1a;AI 【前言】 在Python学习的道路上&#xff0c;练习题是帮助小白快速掌握编程知识和技能的重要工具。然而&#xff0c;…...

iOS15描述文件在哪下载?iOS15测试版描述文件下载与升级教程

iOS 15正式发布&#xff1a;全面升级体验与开发者工具推荐 今天凌晨&#xff0c;备受关注的WWDC21开发者大会上如期召开&#xff0c;果粉期待已久的新一代iOS 15操作系统正式发布。iOS 15系统带来了全新FaceTime与通知界面&#xff0c;并对照片、天气、钱包、地图等应用进行了…...

Java面试(2025)—— Spring

什么是Spring? 结构化回答&#xff08;总分总模式&#xff09; ① 一句话定义 “Spring 是一个开源的 Java 企业级应用框架&#xff0c;核心目标是简化企业应用的开发&#xff0c;通过控制反转&#xff08;IoC&#xff09;、依赖注入&#xff08;DI&#xff09;和面向切面编…...

【C++ Qt】Hello World、初始信号槽、理解对象树 ~~~(通俗易懂 图文并茂)

每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” 绪论​&#xff1a; 本章是Qt的第二篇&#xff0c;带你认识Qt中几个简单的控件如何实现&#xff0c;以及通过信号槽的方式实现一定的用户和程序的联动&#xff0c;还有许多…...

2025.04.16【GroupedandStackedbarplot】生信数据可视化技法

Negative values This blogpost shows what happens when the dataset includes negative values. Most basic streamchart The most basic streamchart you can build with R and the streamgraph package. 文章目录 Negative valuesMost basic streamchart 2025.04.16【Gro…...

java 设计模式之代理模式

简介 代理模式&#xff1a;使用代理类来增强目标类的功能。在代码结构上&#xff0c;代理对象持有目标对象&#xff0c;通过代理对象访问目标对象&#xff0c;这样可以在不改变目标对象的前提下增加额外的功能&#xff0c;如权限校验、缓存等 代理模式内部的角色&#xff1a;…...

Spring Boot实战:基于策略模式+代理模式手写幂等性注解组件

一、为什么需要幂等性&#xff1f; 核心定义&#xff1a;在分布式系统中&#xff0c;一个操作无论执行一次还是多次&#xff0c;最终结果都保持一致。 典型场景&#xff1a; 用户重复点击提交按钮网络抖动导致的请求重试消息队列的重复消费支付系统的回调通知 不处理幂等的风…...

【.net core】【watercloud】数据库连接报错问题

错误信息&#xff1a; 中文提示 : 连接数据库过程中发生错误&#xff0c;检查服务器是否正常连接字符串是否正确&#xff0c;错误信息&#xff1a;Cannot Open when State is Connecting.DbType"MySql";ConfigId"0". English Message : Connection open …...

69. x 的平方根

目录 一、问题描述 二、解题思路 三、代码 四、复杂度分析 一、问题描述 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。 注意&#xff1a;不允许使用任何内置指数…...

计算机网络基础概论

计算机网络基础概论 目录 一、网络基本概念 1.1. 网络 1.2 互联网 1.3 ip地址 1.3.1 作用 1.3.2 分类 1.4 MAC地址 1.4.1 MAC地址与 IP 地址的关系 1.5 网络协议 二、网络分层模型 2.1 物理层 2.2 数据链路层 2.3 网络层 2.4 传输层 2.5 会话层 2.6 表示层 2.7…...

京东3D空间视频生成技术探索与应用

1. 背景 近年来&#xff0c;随着社交媒体、流媒体平台以及XR设备的快速发展&#xff0c;沉浸式3D空间视频的需求迅猛增长&#xff0c;尤其是在短视频、直播和电影领域&#xff0c;正在重新定义观众的观看体验。2023年&#xff0c;苹果公司发布的空间视频技术为这一趋势注入了新…...

吉利矩阵(DFS)

所有元素为非负整数&#xff0c;且各行各列的元素和都等于 7 的 33 方阵称为 “吉利矩阵”&#xff0c;因为这样的矩阵一共有 666 种。 本题就请你统计一下&#xff0c;各行各列的元素和都等于 5 的 33 方阵一共有多少种&#xff1f; 思路&#xff1a;统计方法数&#xff0c;…...

突破反爬限制的智能数据采集实战 —— 面向中小企业的高效信息监控方案

在当前数据驱动的商业环境中&#xff0c;如何高效、稳定地获取网络数据&#xff0c;已成为众多中小企业进行市场洞察、竞品监测与品牌舆情管理的关键能力。本文将分享一个基于先进API技术构建的社交媒体热点监控系统&#xff0c;聚焦实际应用场景&#xff0c;展示如何在合规前提…...

从0到1:让AI赋能计算机的全流程实践指南

&#x1f381;个人主页&#xff1a;User_芊芊君子 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 &#x1f50d;系列专栏&#xff1a;AI 【前言】 在数字化浪潮席卷全球的今天&#xff0c;AI&#xff08;人工智能&#xff09;早已不是科幻电影中的虚构概…...

IntelliJ IDEA 2025.1 发布 ,默认 K2 模式 | Android Studio 也将跟进

2025.1 版本已经发布&#xff0c;在此之前我们就聊过该版本的 《Terminal 又发布全新重构版本》&#xff0c;而现在 2025.1 中的 K2 模式也成为了默认选项。 可以预见&#xff0c;这个版本可能会包含不少大坑&#xff0c;为下个 Android Studio 祈祷。 首先有一点可以确定&…...

MCP、A2A、Function Calling:AI架构设计的三驾马车

随着AI浪潮的到来&#xff0c;各种技术和概念也层出不穷&#xff0c;作为技术人应该第一时间掌握其核心概念与原理&#xff0c;以便于在工作和交流中傻傻分不清楚&#xff0c;本文主要就最近大家提及比较多的MCP、A2A和Function Call做下普及与区分 在当今快速发展的AI领域&a…...

NO.96十六届蓝桥杯备战|图论基础-多源最短路|Floyd|Clear And Present Danger|灾后重建|无向图的最小环问题(C++)

多源最短路&#xff1a;即图中每对顶点间的最短路径 floyd算法本质是动态规划&#xff0c;⽤来求任意两个结点之间的最短路&#xff0c;也称插点法。通过不断在两点之间加⼊新的点&#xff0c;来更新最短路。 适⽤于任何图&#xff0c;不管有向⽆向&#xff0c;边权正负&…...

OpenHarmony - 小型系统内核(LiteOS-A)(六)

OpenHarmony - 小型系统内核&#xff08;LiteOS-A&#xff09;&#xff08;六&#xff09; 七、文件系统 支持的文件系统 FAT 基本概念 FAT文件系统是File Allocation Table&#xff08;文件配置表&#xff09;的简称&#xff0c;主要包括DBR区、FAT区、DATA区三个区域。其…...

“星睿O6” AI PC开发套件评测 - Windows on Arm 安装指南和性能测评

引言 Radxa联合此芯科技和安谋科技推出全新的"星睿O6"迷你 ITX 主板。该系统搭载了 CIX P1&#xff08;CD8180&#xff09;12 核 Armv9 处理器&#xff0c;拥有高达30T算力的NPU和高性能的GPU&#xff0c;最高配备64GB LPDDR内存&#xff0c;并提供了如 5GbE、HDMI …...

JS实现RSA加密

目录 目标 环境 实现RSA加解密 计算RSA加密允许的最大字节长度 目标 使用JS实现RSA加密解密。计算RSA加密允许的最大字节长度。 环境 node-rsa 实现RSA加解密 const NodeRSA require(node-rsa);function getKey() {const keyLength512// 创建 RSA 密钥对const key new …...

Seata方案详细

Seata&#xff08;Simple Extensible Autonomous Transaction Architecture&#xff09;是阿里开源的分布式事务解决方案&#xff0c;支持多种事务模式&#xff0c;提供一站式的事务管理能力。以下是其核心原理、模式及实践的详细解析&#xff1a; 一、Seata核心架构与角色 Se…...

深入了解v-model的原理:v-model拆分为value属性和input事件,表单类组件的封装并用v-model简化代码

文章目录 1.v-model的原理1.1.验证:在input文本输入框中不使用v-model实现双向数据绑定1.2.验证:v-model在下拉菜单中的拆分 2.表单类组件的封装2.1.原理或步骤2.2.示例:表单类组件封装之下拉菜单select的封装 3.使用v-model简化代码完整代码 4.拓展示例:完成input文本输入框的…...

设计模式每日硬核训练 Day 14:组合模式(Composite Pattern)完整讲解与实战应用

&#x1f504; 回顾 Day 13&#xff1a;桥接模式小结 在 Day 13 中&#xff0c;我们学习了桥接模式&#xff08;Bridge Pattern&#xff09;&#xff1a; 用于将“抽象”与“实现”分离&#xff0c;适用于双维度变化场景&#xff08;如图形类型 渲染方式&#xff09;。它强调…...

RMSIN论文阅读

自适应旋转卷积 (ARC)是否可以换成可变形卷积 研究背景 指向性遥感图像分割&#xff08;RRSIS&#xff09;&#xff1a;旨在根据文本描述实现遥感图像中目标对象的像素级定位 像素级定位&#xff1a;像素级定位指的是在图像中对目标对象的每个像素进行准确的定位和标记。这意味…...

【音视频】FLV格式分析

FLV概述 FLV(Flash Video)是Adobe公司推出的⼀种流媒体格式&#xff0c;由于其封装后的⾳视频⽂件体积⼩、封装简单等特点&#xff0c;⾮常适合于互联⽹上使⽤。⽬前主流的视频⽹站基本都⽀持FLV。采⽤FLV格式封装的⽂件后缀为.flv。 FLV封装格式是由⼀个⽂件头(file header)和…...

华为OD机试真题——最小的调整次数/特异性双端队列(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析&#xff1b; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式&#xff01; 2025华为OD真题目录全流程解析/备考攻略/经验分享 华为OD机试真题《最小的调…...

华为OD机试真题——统计匹配的二元组个数(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析&#xff1b; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式&#xff01; 2025华为OD真题目录全流程解析/备考攻略/经验分享 华为OD机试真题《统计匹配…...