【2024第一期CANN训练营】3、AscendCL运行时管理

文章目录

  • 【2024第一期CANN训练营】3、AscendCL运行时管理
    • 1. 初始化与去初始化
    • 2. 资源申请与释放
      • 2.1 申请流程
      • 2.2 释放流程
      • 2.3 运行模式(可选)
    • 3. 数据传输
      • 3.1 接口调用流程
      • 3.2 主要数据传输场景
        • 1. Host内的数据传输
        • 2. 从Host到Device的数据传输
        • 3. 从Device到Host的数据传输
        • 4. 一个Device内的数据传输
        • 5. 两个Device间的数据传输
    • 4. Stream管理
      • 4.1 单线程单Stream
      • 4.2 单线程多Stream
      • 4.3 多线程多Stream
    • 5. 多Device切换
      • 5.1 多Device切换关键接口
      • 5.2 多Device切换流程
    • 6. 同步等待
      • 6.1 Event的同步等待
      • 6.2 Stream内任务的同步等待
      • 6.3 Stream间任务的同步等待
      • 6.4 Device的同步等待

【2024第一期CANN训练营】3、AscendCL运行时管理

本教程将介绍如何使用昇腾社区AscendCL应用开发接口进行运行时管理。并从AscendCL的初始化与去初始化、运行管理资源的申请与释放、数据传输、Stream管理、多Device切换以及同步等待等关键步骤来展开内容

以下教程涉及的所有代码都可以从样例介绍中获得

1. 初始化与去初始化

在使用AscendCL进行开发前,首先需要初始化AscendCL环境。这可以通过调用aclInit接口来完成。如果默认配置已满足需求,可以直接传入NULL。

aclError ret = aclInit(NULL);

完成所有AscendCL调用后,需要调用aclFinalize接口去初始化AscendCL。

ret = aclFinalize();

2. 资源申请与释放

运行管理资源包括Device、Context和Stream。申请和释放这些资源的顺序很重要。

2.1 申请流程

  1. 使用aclrtSetDevice显式指定运算的Device。
  2. 通过aclrtCreateContext创建Context。
  3. 使用aclrtCreateStream创建Stream。

示例代码:

// 初始化变量
int32_t deviceId=0 ;
aclrtContext context;
aclrtStream stream;aclError ret = aclrtSetDevice(deviceId);
ret = aclrtCreateContext(&context, deviceId);
ret = aclrtCreateStream(&stream);

2.2 释放流程

  1. 使用aclrtDestroyStream销毁Stream。
  2. 通过aclrtDestroyContext销毁Context。
  3. 调用aclrtResetDevice重置Device。

示例代码:

ret = aclrtDestroyStream(stream);
ret = aclrtDestroyContext(context);
ret = aclrtResetDevice(deviceId);

2.3 运行模式(可选)

获取当前昇腾AI软件栈的运行模式,根据不同的运行模式,后续的接口调用方式不同

  • 如果查询结果为ACL_HOST,则数据传输时涉及申请Host上的内存。
  • 如果查询结果为ACL_DEVICE,则数据传输时仅需申请Device上的内存。
aclrtRunMode runMode;
extern bool g_isDevice;ret = aclrtGetRunMode(&runMode);
g_isDevice = (runMode == ACL_DEVICE);

3. 数据传输

数据传输包含申请内存,将数据读入内存,内存复制三个环节

3.1 接口调用流程

  1. 申请内存
    • 在Host上申请内存可以使用C++标准库中的newmalloc,或者使用AscendCL提供的aclrtMallocHost接口。
    • 在Device上申请内存则需要使用aclrtMalloc接口。
  2. 将数据读入内存:用户需要自行管理数据读入内存的实现逻辑。
  3. 内存复制:通过内存复制实现数据传输,可以选择同步或异步内存复制。
    • 同步内存复制使用aclrtMemcpy接口
    • 异步内存复制使用aclrtMemcpyAsync接口,并配合aclrtSynchronizeStream接口实现同步等待。

3.2 主要数据传输场景

1. Host内的数据传输

当前仅支持调用aclrtMemcpy接口执行同步Host内的内存复制任务,不支持调用aclrtMemcpyAsync接口执行异步Host内的内存复制功能

// 申请内存
uint64_t size = 1 * 1024 * 1024;
void* hostPtrA = NULL;
void* hostPtrB = NULL;
aclrtMallocHost(&hostPtrA, size);
aclrtMallocHost(&hostPtrB, size);// 向内存中读入数据
ReadFile(fileName, hostPtrA, size);// 同步内存复制
aclrtMemcpy(hostPtrB, size, hostPtrA, size, ACL_MEMCPY_HOST_TO_HOST);// 释放资源
aclrtFreeHost(hostPtrA);
aclrtFreeHost(hostPtrB);
2. 从Host到Device的数据传输

既支持同步内存复制,又支持异步内存复制

  • 同步内存复制
// 申请内存
uint64_t size = 1 * 1024 * 1024;
void* hostPtrA = NULL;
void* devPtrB = NULL;
aclrtMallocHost(&hostPtrA, size);
aclrtMalloc(&devPtrB, size, ACL_MEM_MALLOC_NORMAL_ONLY);// 向内存中读入数据
ReadFile(fileName, hostPtrA, size);// 同步内存复制
aclrtMemcpy(devPtrB, size, hostPtrA, size, ACL_MEMCPY_HOST_TO_DEVICE);// 释放资源
aclrtFreeHost(hostPtrA);
aclrtFree(devPtrB);
  • 异步内存复制
// 申请内存
uint64_t size = 1 * 1024 * 1024;
void* hostAddr = NULL;
void* devAddr = NULL;
aclrtMallocHost(&hostAddr, size + 64);
aclrtMalloc(&devAddr, size, ACL_MEM_MALLOC_NORMAL_ONLY);
aclrtStream stream = NULL;
aclrtCreateStream(&stream);// 获取到64字节对齐的地址
char *hostAlignAddr =(char *)hostAddr + 64 - ((uintptr_t)hostAddr % 64);// 向内存中读入数据
ReadFile(fileName, hostAlignAddr, size);// 异步内存复制
aclrtMemcpyAsync(devAddr, size, hostAlignAddr, size, ACL_MEMCPY_HOST_TO_DEVICE, stream);
aclrtSynchronizeStream(stream);// 释放资源
aclrtDestroyStream(stream);
aclrtFreeHost(hostAddr);
aclrtFree(devAddr);
3. 从Device到Host的数据传输

既支持同步内存复制,又支持异步内存复制

  • 同步内存复制
// 申请内存
uint64_t size = 1 * 1024 * 1024;
void* devPtrA = NULL;
void* hostPtrB = NULL;
aclrtMalloc(&devPtrA, size, ACL_MEM_MALLOC_NORMAL_ONLY);
aclrtMallocHost(&hostPtrB, size);// 向内存中读入数据
ReadFile(fileName, devPtrA, size);// 同步内存复制
aclrtMemcpy(hostPtrB, size, devPtrA, size, ACL_MEMCPY_DEVICE_TO_HOST);// 释放资源
aclrtFree(devPtrA);
aclrtFreeHost(hostPtrB);
  • 异步内存复制
// 申请内存
uint64_t size = 1 * 1024 * 1024;
void* hostAddr = NULL;
void* devAddr = NULL;
aclrtMallocHost(&hostAddr, size + 64);
aclrtMalloc(&devAddr, size, ACL_MEM_MALLOC_NORMAL_ONLY);
aclrtStream stream = NULL;
aclrtCreateStream(&stream);// 向内存中读入数据
ReadFile(fileName, devAddr, size);// 获取到64字节对齐的地址
char *hostAlignAddr =(char *)hostAddr + 64 - ((uintptr_t)hostAddr % 64);// 异步内存复制
aclrtMemcpyAsync(hostAlignAddr, size, devAddr, size, ACL_MEMCPY_DEVICE_TO_HOST, stream);
aclrtSynchronizeStream(stream);// 释放资源
aclrtDestroyStream(stream);
aclrtFreeHost(hostAddr);
aclrtFree(devAddr);
4. 一个Device内的数据传输
// 申请内存
uint64_t size = 1 * 1024 * 1024;
void* devPtrA = NULL;
void* devPtrB = NULL;
aclrtMalloc(&devPtrA, size, ACL_MEM_MALLOC_NORMAL_ONLY);
aclrtMalloc(&devPtrB, size, ACL_MEM_MALLOC_NORMAL_ONLY);// 向内存中读入数据
ReadFile(fileName, devPtrA, size);// 同步内存复制
aclrtMemcpy(devPtrB, size, devPtrA, size, ACL_MEMCPY_DEVICE_TO_DEVICE);// 异步内存复制
aclrtStream stream;
aclrtCreateStream(&stream);
aclrtMemcpyAsync(devPtrB, size, devPtrA, size, ACL_MEMCPY_DEVICE_TO_DEVICE, stream);
aclrtSynchronizeStream(stream);// 释放资源
aclrtFree(devPtrA);
aclrtFree(devPtrB);
5. 两个Device间的数据传输
  • Atlas 200/300/500 推理产品上,不支持该功能。
  • Atlas 200/500 A2推理产品,不支持该功能。
// AscendCL初始化
auto ret = aclInit(NULL);// 查询Device 0和Device 1之间是否支持内存复制
int32_t canAccessPeer = 0;
ret = aclrtDeviceCanAccessPeer(&canAccessPeer, 0, 1);// 1表示支持内存复制
if (canAccessPeer == 1) {// Device 0下的操作,包括内存申请、数据写入、内存复制等ret = aclrtSetDevice(0);		void *dev0;ret = aclrtMalloc(&dev0, 10, ACL_MEM_MALLOC_HUGE_FIRST_P2P);ret = aclrtMemset(dev0, 10, 1, 10);// Device 1下的操作ret = aclrtSetDevice(1);ret = aclrtDeviceEnablePeerAccess(0, 0);void *dev1;ret = aclrtMalloc(&dev1, 10, ACL_MEM_MALLOC_HUGE_FIRST_P2P);ret = aclrtMemset(dev1, 10, 0, 10);// 执行复制,将Device 0上的内存数据复制到Device 1上ret = aclrtMemcpy(dev1, 10, dev0, 10, ACL_MEMCPY_DEVICE_TO_DEVICE);ret = aclrtResetDevice(1);ret = aclrtSetDevice(0);ret = aclrtResetDevice(0);printf("P2P copy success\n");
} else {printf("current device doesn't support p2p feature\n");
}// AscendCL去初始化
aclFinalize();

注意事项

  • 在进行数据传输时,需要确保内存申请和释放的正确性,避免内存泄漏。
  • 异步内存复制时,需要确保内存地址的64字节对齐。
  • 在使用AscendCL进行数据传输时,应该增加异常处理逻辑,以便于及时发现并解决问题。

4. Stream管理

在AscendCL应用开发中,Stream是任务队列的抽象,用于管理任务的并行执行。理解并有效管理Stream对于提升程序性能和资源利用率至关重要。AscendCL提供了以下几种Stream管理机制:

4.1 单线程单Stream

在单线程环境下,可以创建一个Stream来管理任务的执行。

#include "acl/acl.h"// 显式创建一个Stream
aclrtStream stream;
aclrtCreateStream(&stream);// 调用触发任务的接口,传入stream参数
aclrtMemcpyAsync(dstPtr, dstSize, srcPtr, srcSize, ACL_MEMCPY_HOST_TO_DEVICE, stream);// 调用aclrtSynchronizeStream接口,阻塞应用程序运行,直到指定Stream中的所有任务都完成。
aclrtSynchronizeStream(stream);// Stream使用结束后,显式销毁Stream
aclrtDestroyStream(stream);

4.2 单线程多Stream

在单线程环境下,可以创建多个Stream来并行执行不同的任务。

#include "acl/acl.h"
int32_t deviceId = 0;
uint32_t modelId1 = 0;
uint32_t modelId2 = 1;// 显式创建一个Stream
aclrtContext context;
aclrtStream stream1, stream2;// 创建Context
aclrtCreateContext(&context, deviceId);// 创建stream1
aclrtCreateStream(&stream1);
// 调用触发任务的接口,例如异步模型推理,任务下发在stream1
aclmdlDataset *input1, *output1;
aclmdlExecuteAsync(modelId1, input1, output1, stream1);// 创建stream2
aclrtCreateStream(&stream2);
// 调用触发任务的接口,例如异步模型推理,任务下发在stream2
aclmdlDataset *input2, *output2;
aclmdlExecuteAsync(modelId2, input2, output2, stream2);// 流同步
aclrtSynchronizeStream(stream1);
aclrtSynchronizeStream(stream2);// 释放资源
aclrtDestroyStream(stream1);
aclrtDestroyStream(stream2);
aclrtDestroyContext(context);

4.3 多线程多Stream

在多线程环境下,每个线程可以创建自己的Stream来执行任务。

#include "acl/acl.h"void runThread(aclrtStream stream) {int32_t deviceId = 0;aclrtContext context;// 创建ContextaclrtCreateContext(&context, deviceId);// 显式创建一个StreamaclrtStream threadStream;aclrtCreateStream(&threadStream);// 释放资源aclrtDestroyStream(threadStream);aclrtDestroyContext(context);
}// 创建2个线程,每个线程对应一个Stream
aclrtStream stream1, stream2;
std::thread t1(runThread, stream1);
std::thread t2(runThread, stream2);// 显式调用join函数确保结束线程
t1.join();
t2.join();

注意事项

  • 在创建Stream之前,确保已经创建了Context。
  • 在多Stream场景下,注意使用aclrtSynchronizeStream接口来同步任务的执行。
  • 在多线程环境下,确保每个线程正确地创建和销毁自己的Stream和Context。
  • 在程序结束前,确保释放所有Stream和Context资源,避免内存泄漏。

5. 多Device切换

在AscendCL应用开发中,多Device切换是一个重要的特性,它允许开发者在多个昇腾AI处理器(Device)之间高效地切换和管理任务。

下图为:同步等待流程_多Device场景

img

5.1 多Device切换关键接口

  1. aclrtSetCurrentContext:用于切换当前线程的Context,比使用aclrtSetDevice接口效率更高。

  2. aclrtSynchronizeDevice:用于等待特定Device上的所有计算任务结束。

5.2 多Device切换流程

  1. 初始化AscendCL:在使用AscendCL进行任何操作之前,需要先初始化AscendCL。

    aclError ret = aclInit(NULL);
    if (ret != ACL_ERROR_NONE) {// 错误处理
    }
    
  2. 创建Context:在多Device环境中,每个Device都有一个Context。需要为每个Device创建一个Context。

    aclrtContext context[DEVICE_NUM];
    for (int i = 0; i < DEVICE_NUM; ++i) {ret = aclrtCreateContext(&context[i], i);if (ret != ACL_ERROR_NONE) {// 错误处理}
    }
    
  3. 切换Context和Device:在执行任务时,使用aclrtSetCurrentContext接口切换到相应的Context,从而在对应的Device上执行任务。

    // 假设我们要在Device 1上执行任务
    aclrtSetCurrentContext(context[1]);
    // 执行任务...
    
  4. 等待Device任务完成:在需要等待特定Device上的任务完成时,使用aclrtSynchronizeDevice接口。

    // 等待Device 2上的任务完成
    aclrtSynchronizeDevice(2);
    
  5. 执行任务:在每个Device上执行相应的任务,如模型推理或算子执行。

    // 模型推理示例
    aclmdlExecuteAsync(modelId, input, output, stream);
    
  6. 释放资源:在任务完成后,释放Context和销毁所有资源。

    for (int i = 0; i < DEVICE_NUM; ++i) {aclrtDestroyContext(context[i]);
    }
    aclFinalize();
    

注意事项

  • 在多Device环境中,确保为每个Device创建了对应的Context。
  • 使用aclrtSetCurrentContext接口切换Context时,确保当前线程没有其他Device的任务在执行。
  • 在等待Device任务完成时,确保没有其他任务依赖于这些任务的结果,否则可能会导致死锁。
  • 在程序结束前,确保释放所有Context资源,并调用aclFinalize进行AscendCL的清理。

6. 同步等待

在AscendCL应用开发中,同步等待是一个关键的概念,它确保了在异步计算场景下任务的正确执行顺序和资源的正确管理

AscendCL提供了以下同步机制:

  1. Event的同步等待:使用aclrtSynchronizeEvent接口,阻塞应用程序运行,等待Event完成。
  2. Stream内任务的同步等待:使用aclrtSynchronizeStream接口,阻塞应用程序运行,直到指定Stream中的所有任务都完成。
  3. Stream间任务的同步等待:使用aclrtStreamWaitEvent接口,阻塞指定Stream的运行,直到指定的Event完成。
  4. Device的同步等待:使用aclrtSynchronizeDevice接口,阻塞应用程序运行,直到正在运算中的Device完成运算。

6.1 Event的同步等待

#include "acl/acl.h"// 创建一个Event
aclrtEvent event;
aclrtCreateEvent(&event);// 显式创建一个Stream
aclrtStream stream;
aclrtCreateStream(&stream);// 在stream末尾添加了一个event
aclrtRecordEvent(event, stream);// 阻塞应用程序运行,等待event发生,也就是stream执行完成
aclrtSynchronizeEvent(event);// 显式销毁资源
aclrtDestroyStream(stream);
aclrtDestroyEvent(event);

6.2 Stream内任务的同步等待

#include "acl/acl.h"// 显式创建一个Stream
aclrtStream stream;
aclrtCreateStream(&stream);// 调用触发任务的接口,传入stream参数
aclrtMemcpyAsync(dstPtr, dstSize, srcPtr, srcSize, ACL_MEMCPY_HOST_TO_DEVICE, stream);// 调用aclrtSynchronizeStream接口,阻塞应用程序运行,直到指定Stream中的所有任务都完成
aclrtSynchronizeStream(stream);// Stream使用结束后,显式销毁Stream
aclrtDestroyStream(stream);

6.3 Stream间任务的同步等待

#include "acl/acl.h"// 创建一个Event
aclrtEvent event;
aclrtCreateEvent(&event);// 创建stream1
aclrtStream s1;
aclrtCreateStream(&s1);// 创建stream2
aclrtStream s2;
aclrtCreateStream(&s2);// 在s1末尾添加了一个event
aclrtRecordEvent(event, s1);// 阻塞s2运行,直到指定event发生,也就是s1执行完成
aclrtStreamWaitEvent(s2, event);// 显式销毁资源
aclrtDestroyStream(s2);
aclrtDestroyStream(s1);
aclrtDestroyEvent(event);

6.4 Device的同步等待

#include "acl/acl.h"// 指定device
aclrtSetDevice(0);// 创建context
aclrtContext ctx;
aclrtCreateContext(&ctx, 0);// 创建stream
aclrtStream stream;
aclrtCreateStream(&stream);// 阻塞应用程序运行,直到正在运算中的Device完成运算
aclrtSynchronizeDevice();// 资源销毁
aclrtDestroyStream(stream);
aclrtDestroyContext(ctx);
aclrtResetDevice(0);

注意事项

  • 在使用同步等待机制时,确保正确地创建和销毁Event和Stream资源。
  • 在多Stream环境中,使用Event和aclrtStreamWaitEvent接口来实现Stream间的同步等待。
  • 在多Device环境中,使用aclrtSynchronizeDevice接口来等待特定Device上的任务完成。
  • 在程序结束前,确保释放所有资源,避免内存泄漏。。

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

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

相关文章

排序算法:快速排序(递归)

文章目录 一、创始人托尼霍尔的快速排序二、挖坑法三、前后指针法 所属专栏:C初阶 引言&#xff1a;这里所说的快速排序有三种&#xff0c;第一种是霍尔大佬自创的&#xff0c;还有一种叫做挖坑法&#xff0c;另外一种叫前后指针法 一、创始人托尼霍尔的快速排序 1.这里我们先…

拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

MySQL 篇- Java 连接 MySQL 数据库并实现数据交互

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 JDBC 概述 2.0 实现 Java 连接 MySQL 数据库并实现数据交互的完整过程 2.1 安装数据库驱动包 2.2 创建数据源对象 2.3 获取数据库连接对象 2.4 创建 SQL 语句 2.…

8.Python从入门到精通—Python 字符串,转义字符,字符串运算符

8.Python从入门到精通—Python 字符串,转义字符,字符串运算符 Python 字符串创建字符串访问字符串中的字符字符串切片字符串操作符字符串方法 Python 转义字符Python字符串运算符 Python 字符串 在 Python 中&#xff0c;字符串是一种基本数据类型&#xff0c;用于表示文本数据…

构建部署_Docker常用命令

构建部署_Docker常见命令 启动命令镜像命令容器命令 启动命令 启动docker&#xff1a;systemctl start docker 停止docker&#xff1a;systemctl stop docker 重启docker&#xff1a;systemctl restart docker 查看docker状态&#xff1a;systemctl status docker 开机启动&…

Java微服务分布式事务框架seata

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

SSH远程连接断开后,程序继续运行

1、问题 我们在使用SSH连接远程服务器跑代码的时候&#xff0c;可能会遇到 代码需要跑很久 的情况&#xff0c;你可能会想 断开远程连接&#xff0c;但是&#xff0c;代码仍然要继续跑。 (eg: 晚上关电脑&#xff0c;但是想让代码继续跑着&#xff0c;第二天想看结果) 2、scre…

哪里有视频素材网站免费下载?高清烟花视频素材哪里有?

如果你在寻找那些能点亮夜空的绚丽烟花视频素材&#xff0c;或者无水印的高清视频素材&#xff0c;那下面这些资源网站将会是你的宝库。今天&#xff0c;我要分享给你一些最佳的无水印视频素材下载网站&#xff0c;让你的视频制作闪耀起来。 1.蛙学府 这个网站是视频创作者的天…

Centos strema 9 环境部署Glusterfs9

本文档只是创建复制卷&#xff0c;分布式卷&#xff0c;分布式复制卷&#xff0c;纠删卷 操作系统 内核 角色 Ip地址 说明 CentOS Stream 9 x86_64 5.14.0-427.el9.x86_64 客户端 client 192.168.80.119 挂载存储业务机器 CentOS Stream 9 x86_64 5.14.0-427.el9.x8…

开展“人工智能+”行动,Gooxi与你一起奔赴新质未来

在今年两会上&#xff0c;“新质生产力”成为了反复被提及的热词。在政府发布的工作报告中“大力推进现代化产业体系建设&#xff0c;加快发展新质生产力”更是被置于政府工作任务的首位。具体说来&#xff0c;发展新质生产力包括产业链升级、培育新产业、推进数字经济建设三方…

力扣每日练习(3.15)补

112. 路径总和 解题思路&#xff1a;遍历出每条路径&#xff0c;使得总和为目标值。如果找到了&#xff0c;就是1.否则为0. 如果遍历到了叶节点&#xff0c;就计算是否达到了目标值&#xff1b; 如果没有遍历到叶节点&#xff0c;就继续往左右子树遍历。 def hasPathSum(root…

Linux: 动态库与静态库

静态库: .a后缀 动态库: .so后缀 当动静态库同时存在的时候, 默认优先使用动态库 1.1生成动静态库 Archive files 归档文件 r : replace c : create 命令: ar -rc lib库名.a mymath.o myprint.o //例如: ar -rc libhello.a mymath.o myprint.o Ma…

linux安装anconda

第一步&#xff1a; 下载anaconda 下载地址&#xff1a;&#xff08;选择Linux版本的&#xff09; https://repo.anaconda.com/archive/第二步&#xff1a; 把下载好的anaconda放到指定的路径 然后在该路径下&#xff08;我是直接放属于我的根目录下&#xff09; 输入以下命令…

axios 请求 url 地址,判断网络地址是否存在

使用 axios 来判断一个 URL 地址是否可连接&#xff0c;通常涉及到发送一个 HTTP 请求到这个地址&#xff0c;并检查响应的状态码。如果请求成功&#xff0c;并且返回了 200 OK 状态码&#xff0c;那么通常可以认为这个地址是可连接的。 以下是一个简单的示例&#xff0c;使用…

国创证券|资源再生概念持续活跃,超越科技两连板,大地海洋等走高

资源再生概念15日盘中再度走强&#xff0c;截至发稿&#xff0c;超越科技涨停斩获两连板&#xff0c;深水海纳涨超14%&#xff0c;大地海洋涨超12%&#xff0c;华新环保涨近9%&#xff0c;天奇股份、格林美、怡球资源等涨超5%。 消息面上&#xff0c;3月13日&#xff0c;国务院…

ElasticSearch架构设计

一、基础概念 Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene™ 基础上的搜索引擎.当然 Elasticsearch 并不仅仅是 Lucene 那么简单&#xff0c;它不仅包括了全文搜索功能&#xff0c;还可以进行以下工作: 一个分布式的实时文档…

油烟净化器:餐饮卫生环保检测的必备之选

我最近分析了餐饮市场的油烟净化器等产品报告&#xff0c;解决了餐饮业厨房油腻的难题&#xff0c;更加方便了在餐饮业和商业场所有需求的小伙伴们。 在如今日益关注卫生环保的时代背景下&#xff0c;油烟净化器成为餐饮业者必备的环保设备&#xff0c;不仅能够保持餐饮环境清…

【2024第一期CANN训练营】2、AscendCL概述

文章目录 【2024第一期CANN训练营】2、AscendCL概述1. AscendCL架构及基本概念1.1 什么是AscendCL&#xff1f;1.2 AscendCL的优势1.3 AscendCL应用场景1.4 基本概念 2. AscendCL接口调用流程2.1 流程概述2.2 详细步骤2.3 头文件和库文件 3. 准备开发和运行环境3.1 部署环境3.2…

文档解析应该获取哪些知识?

一、背景 随着人工智能和机器学习技术的发展&#xff0c;我们现在有能力从这些文档中提取更加丰富和深入的信息。无论是为了内容管理、知识发现还是数据分析&#xff0c;这些技术都为我们提供了强大的工具&#xff0c;以更有效地利用PDF文档中的知识。随着技术的不断进步&…

便携式气象站的工作原理

TH-BQX9便携式自动气象观测仪器是一种集成了多种传感器和自动化技术的气象监测设备&#xff0c;以其便携性、自动化和高精度等特点&#xff0c;广泛应用于气象、环保、农业、科研等领域。 首先&#xff0c;它的便携性是其最大的优势之一。设计紧凑、轻便易携&#xff0c;使得用…