大模型系列11-ray

大模型系列11-ray

  • Plasma
    • PlasmaStore
      • 启动监听
      • 处理请求 ProcessMessage
        • PlasmaCreateRequest请求
        • PlasmaCreateRetryRequest请求
        • PlasmaGetRequest请求
        • PlasmaReleaseRequest
        • PlasmaDeleteRequest
        • PlasmaSealRequest
      • ObjectLifecycleManager
        • GetObject
        • SealObject
      • ObjectStoreRunner
      • PlasmaStoreRunner
      • ObjectStatsCollector
        • OnObjectRefIncreased
      • LocalObject
      • ObjectManager
    • PlasmaClient
    • Plasma编译依赖项
      • plasma_store_server_lib
        • 代码文件
        • 依赖库
      • PlasmaClient
        • 代码文件
        • 依赖库
      • ray_common
        • 依赖库
      • plasma_fbs [done]
        • 代码文件
        • 无依赖库
      • 其它
  • Ray编译运行demo
    • 编译
    • 安装
    • 如何查看当前目录的ray包
      • bazel build基础教程
    • 生成wheel并测试
      • 编译问题
        • 安装 bazel
        • 安装bazel 6.5.0
        • 报错 pack不是class template
        • 报错:error: unused variable 'tag_key' [-Werror=unused-variable]
        • 报错:main/test-filesystem.cc:2:10: fatal error: filesystem: No such file or directory #include <filesystem>
        • 报错:sed: cannot rename python/ray/serve/generated/sedEFwvtV: Permission denied
  • Ray
    • 设计哲学

Plasma

PlasmaStore

启动监听

acceptor启动异步接收新的连接请求,

void PlasmaStore::DoAccept() {
  acceptor_.async_accept(
      socket_,
      boost::bind(&PlasmaStore::ConnectClient, this, boost::asio::placeholders::error));
}

在 Boost.Asio 中,异步操作(如 async_accept)不会自动重新启动,这是由其设计理念决定的。Boost.Asio 的异步操作通常是一次性的,即使一个操作完成了,如果你希望继续处理更多类似的操作,你必须显式地再次调用相应的函数。因此,需要在ConnectClient中再次 DoAccept。

void PlasmaStore::ConnectClient(const boost::system::error_code &error) {
  if (!error) {
    // Accept a new local client and dispatch it to the node manager.
    auto new_connection = Client::Create(
        // NOLINTNEXTLINE : handler must be of boost::AcceptHandler type.
        boost::bind(&PlasmaStore::ProcessMessage, this, ph::_1, ph::_2, ph::_3),
        std::move(socket_));
  }

  if (error != boost::asio::error::operation_aborted) {
    // We're ready to accept another client.
    DoAccept();
  }
}

下面是一个使用boost::asio构建tcp异步服务器监听的例子

#include <boost/asio.hpp>
#include <iostream>

using boost::asio::ip::tcp;

void handle_accept(tcp::socket socket, const boost::system::error_code& error) {
    if (!error) {
        std::string message = "Hello from server!\n";
        boost::asio::write(socket, boost::asio::buffer(message));
        std::cout << "Sent message to client." << std::endl;
    } else {
        std::cerr << "Error: " << error.message() << std::endl;
    }
}

int main() {
    try {
        boost::asio::io_context io_context;

        tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 12345));
        std::cout << "Server is listening on port 12345..." << std::endl;

        while (true) {
            tcp::socket socket(io_context);

            acceptor.async_accept(socket, 
                [&socket](const boost::system::error_code& error) {
                    handle_accept(std::move(socket), error);
                });

            io_context.run();
        }
    } catch (std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

处理请求 ProcessMessage

Status PlasmaStore::ProcessMessage(const std::shared_ptr<Client> &client,
                                   fb::MessageType type,
                                   const std::vector<uint8_t> &message)
PlasmaCreateRequest请求

从请求的 message 字符串中解析成 Request类型,获取相应的请求的属性,如object_id,object_size等

    const auto &object_id = GetCreateRequestObjectId(message);
    const auto &request = flatbuffers::GetRoot<fb::PlasmaCreateRequest>(input);
    const size_t object_size = request->data_size() + request->metadata_size();

如果是 try_immediately == true,则原地执行 TryRequestImmediately,并将结果通过 client->SendFd 返回;否则,将其加入到 create_request_queue_ 队列中,并立刻尝试原地处理,如果本次请求处理有错误,则会触发retry with timeout,该重试请求之后的请求会因为该请求在等待retry中而被自动排队到后面(某个请求被retry,则create_timer_为true),对于排队的请求,会向客户端发送SendUnfinishedCreateReply的回复。

PlasmaCreateRetryRequest请求

客户端收到Unfinished的回复后,可以继续重试,当服务器端收到重试请求后,直接从当前的回复中查找该object_id是否已经完成,如果完成则回复object的location信息,如果未完成,继续回复 SendUnfinishedCreateReply。

PlasmaGetRequest请求

ReadGetRequest 目标是将收到的input字符串解析为PlasmaGetRequest,会拿到其属性,并将请求入队到 get_request_queue_

PlasmaReleaseRequest

调用 ReleaseObject 将 object_id 从client中移除。它会检查 object_lifecycle_mgr_ 中是否有该object_id,如果没有,则直接返回false;如果有,则调用 RemoveFromClientObjectIds 将该object_id移除,这会通过 client->MarkObjectAsUnused(object_id)将object从client的object_ids中移除,同时会将 object_lifecycle_mgr_ 中的object_id的引用计数减1。

PlasmaDeleteRequest

逐个遍历收到的object_id,调用 object_lifecycle_mgr_->DeleteObject将它们移除。 object_lifecycle_mgr_ 内部管理所有的 object_id以及object entry对象。

PlasmaSealRequest

逐个遍历收到的object,调用 object_lifecycle_mgr_.SealObject(object_ids[i]) 将它们seal掉,同时通过 add_object_callback_ 来告知。另外,对pending的get请求标识sealed:get_request_queue_.MarkObjectSealed

MarkObjectSealed

  • 从 object_get_requests_ 获取指定object_id 对应的 get_requests
  • 遍历get_requests,对每个request,将其object_id对应的plasma_object填充(通过object_lifecycle_mgr_.GetObject拿到的entry来填充),调用 object_satisfied_callback_ 来通知外部。如果对于这个get_request,它的所有的object_ids都满足之后,则通过 all_objects_satisfied_callback_ 来通知该get_request。

ObjectLifecycleManager

GetObject

从 object_store_ 获取对象 LocalObject

SealObject

向 object_store_->SealObject(object_id) 发起Seal对象,如果成功,则返回对应的entry。有个状态收集器来通过 stats_collector_->OnObjectSealed(*entry) 来感知各种对象的变化

ObjectStoreRunner

隶属于object_manager.h文件,它创建一个 store_thread_ 线程,启动PlasmaStoreRunner,注意完全单线程逻辑

PlasmaStoreRunner

检查 系统内存, plasma_directory, fallback_directory等信息,然后启动PlasmaStore的run loop,等待外部客户端连接。

构造函数和参数

class PlasmaStoreRunner {
 public:
  PlasmaStoreRunner(std::string socket_name,
                    int64_t system_memory,
                    bool hugepages_enabled,
                    std::string plasma_directory,
                    std::string fallback_directory);
  void Start(ray::SpillObjectsCallback spill_objects_callback,
             std::function<void()> object_store_full_callback,
             ray::AddObjectCallback add_object_callback,
             ray::DeleteObjectCallback delete_object_callback);

主要启动调用

store_.reset(new PlasmaStore(main_service_,
                             *allocator_,
                             *fs_monitor_,
                             socket_name_,
                             RayConfig::instance().object_store_full_delay_ms(),
                             spill_objects_callback,
                             object_store_full_callback,
                             add_object_callback,
                             delete_object_callback));
store_->Start();                             
main_service_.run();                             

ObjectStatsCollector

ObjectStatsCollector 是分布式系统中一个 轻量级但非常重要的组件,专注于对象生命周期的跟踪,空间的使用情况等。

OnObjectRefIncreased

Ray 的设计在引用计数变化的关键节点(0→1 和 1→2)进行了状态更新,主要是为了在性能与资源使用之间取得平衡:

  • 引用计数从 0 到 1:对象引用计数为 0 时,通常意味着它是空闲的,可能被系统标记为可逐出(evictable)或不活跃。当引用计数变为 1 时,说明它开始被使用。标志对象从空闲变为活跃。
    增加正在使用的统计,减少可逐出的统计。
    如果对象封存且由 Worker 创建,标记为可溢出对象,以支持后续的溢出策略(例如,将这些对象移到磁盘以节省内存)
    这是对象从“潜在可清理状态”变为“不可清理状态”的分界点,系统需要在此刻更新相关状态。

  • 引用计数从 1 到 2
    标志对象的重要性提升,进入多任务共享状态。
    溢出操作会涉及磁盘 I/O,代价较高。引用计数增加意味着对象可能正在高频使用,因此通过及时更新“可溢出对象”统计,系统可以避免在不适当的时机溢出对象。

  if (obj.GetRefCount() == 1) {
    num_objects_in_use_++;
    num_bytes_in_use_ += kObjectSize;

    if (kSource == plasma::flatbuf::ObjectSource::CreatedByWorker && kSealed) {
      num_objects_spillable_++;
      num_bytes_spillable_ += kObjectSize;
    }

    if (kSealed) {
      num_objects_evictable_--;
      num_bytes_evictable_ -= kObjectSize;
    }
  }

  // object ref count bump from 1 to 2
  if (obj.GetRefCount() == 2 &&
      kSource == plasma::flatbuf::ObjectSource::CreatedByWorker && kSealed) {
    num_objects_spillable_--;
    num_bytes_spillable_ -= kObjectSize;
  }

LocalObject

唯一标识一个对象,可定位该对象,以及

  • object_info: 对象的信息如数据长度,owner地址信息
  • allocation: 对象所隶属的mmaped chunk的起始位置,包括fd,map_size, offset等信息
  • ref_count: 这个对象的引用计数
  • state: 对象状态,open or sealed
  • source: object来源,用于debug
  • create_time & construct_duration: 创建时间戳以及耗时

ObjectManager

ObjectManager 是 Ray 分布式系统中用于管理 对象的存储、传输和生命周期 的核心组件。它在节点之间协调对象的流动,并与对象存储(如 Plasma Store)交互,确保对象的创建、删除、拉取和推送操作得以高效进行。

  • 支持将对象从一个节点推送(push)到另一个节点(Push 和 PushLocalObject 方法)。
    当节点请求对象时,从其他节点或磁盘拉取(pull)所需的对象(Pull 和 SendPullRequest 方法)。
  • 支持溢出和逐出策略,通过溢出和逐出策略管理内存使用,确保内存资源不会耗尽。通过与 Plasma Store 的交互实现对象溢出(spillable)到磁盘,或者逐出(evictable)以释放内存资源。提供 IsPlasmaObjectSpillable 方法检查对象是否可以溢出。
  • 使用异步 I/O 和多线程(如 rpc_threads_ 和 buffer_pool_),保证高吞吐量和低延迟。通过 buffer_pool_ 管理对象的内存分配和释放,动态调整拉取和推送操作的频率以适应节点的内存状况(UpdatePullsBasedOnAvailableMemory 方法)。对大对象进行分片,支持多线程传输以提升效率(PushObjectInternal 和 SendObjectChunk 方法)。在接收端,处理分片的写入和拼接(ReceiveObjectChunk 方法)。
  • 当对象被创建时,调用 HandleObjectAdded,将对象信息注册到本地记录(如 local_objects_),并通知其他模块。

对象的推送(Push)
如果节点上的某个对象需要传输到其他节点,调用 Push 方法:检查对象是本地的(PushLocalObject)还是在磁盘上(PushFromFilesystem)。对对象进行分片,并通过 RPC 将分片逐一发送(PushObjectInternal 和 SendObjectChunk)。
对象的拉取(Pull)
如果本节点需要一个远程对象,调用 Pull 方法:向目标节点发送拉取请求(SendPullRequest)。
监听对象的位置信息更新,并根据最新信息决定拉取策略。

ObjectManager 和 PlasmaStore的核心区别
ObjectManager 是全局管理者,负责在分布式系统中调度和协调对象的使用。PlasmaStore 是本地存储引擎,专注于高效地管理单节点的共享内存对象。任务请求一个对象,ObjectManager 检查对象是否在本地 PlasmaStore 中。如果存在,直接通过共享内存访问;如果么有,则ObjectManager 向其他节点发送拉取请求,远程节点通过 PlasmaStore 提供数据。
在这里插入图片描述

PlasmaClient

Plasma编译依赖项

plasma_store_server_lib

代码文件
    srcs = [
        "src/ray/object_manager/plasma/create_request_queue.cc",
        "src/ray/object_manager/plasma/dlmalloc.cc",
        "src/ray/object_manager/plasma/eviction_policy.cc",
        "src/ray/object_manager/plasma/get_request_queue.cc",
        "src/ray/object_manager/plasma/object_lifecycle_manager.cc",
        "src/ray/object_manager/plasma/object_store.cc",
        "src/ray/object_manager/plasma/plasma_allocator.cc",
        "src/ray/object_manager/plasma/stats_collector.cc",
        "src/ray/object_manager/plasma/store.cc",
        "src/ray/object_manager/plasma/store_runner.cc",
    ],
    hdrs = [
        "src/ray/object_manager/common.h",
        "src/ray/object_manager/plasma/allocator.h",
        "src/ray/object_manager/plasma/create_request_queue.h",
        "src/ray/object_manager/plasma/eviction_policy.h",
        "src/ray/object_manager/plasma/get_request_queue.h",
        "src/ray/object_manager/plasma/object_lifecycle_manager.h",
        "src/ray/object_manager/plasma/object_store.h",
        "src/ray/object_manager/plasma/plasma_allocator.h",
        "src/ray/object_manager/plasma/stats_collector.h",
        "src/ray/object_manager/plasma/store.h",
        "src/ray/object_manager/plasma/store_runner.h",
        "src/ray/thirdparty/dlmalloc.c",
    ],
依赖库
        ":plasma_client",
        ":stats_lib",
        "//src/ray/common:network",

PlasmaClient

代码文件
srcs = [
        "src/ray/object_manager/common.cc",
        "src/ray/object_manager/plasma/client.cc",
        "src/ray/object_manager/plasma/connection.cc",
        "src/ray/object_manager/plasma/malloc.cc",
        "src/ray/object_manager/plasma/plasma.cc",
        "src/ray/object_manager/plasma/protocol.cc",
        "src/ray/object_manager/plasma/shared_memory.cc",
    ] + select({
        "@platforms//os:windows": [
        ],
        "//conditions:default": [
            "src/ray/object_manager/plasma/fling.cc",
        ],
    }),
    hdrs = [
        "src/ray/object_manager/common.h",
        "src/ray/object_manager/plasma/client.h",
        "src/ray/object_manager/plasma/common.h",
        "src/ray/object_manager/plasma/compat.h",
        "src/ray/object_manager/plasma/connection.h",
        "src/ray/object_manager/plasma/malloc.h",
        "src/ray/object_manager/plasma/plasma.h",
        "src/ray/object_manager/plasma/plasma_generated.h",
        "src/ray/object_manager/plasma/protocol.h",
        "src/ray/object_manager/plasma/shared_memory.h",
    ] + select({
        "@platforms//os:windows": [
        ],
        "//conditions:default": [
            "src/ray/object_manager/plasma/fling.h",
        ],
    }),
依赖库
        ":plasma_fbs",
        ":ray_common",
        "//src/ray/protobuf:common_cc_proto",
        "//src/ray/util",
        "@msgpack",

ray_common

依赖库
ray_cc_library(
    name = "ray_common",
    deps = [
        ":stats_metric",
        "//src/ray/common:asio",
        "//src/ray/common:constants",
        "//src/ray/common:event_stats",
        "//src/ray/common:file_system_monitor",
        "//src/ray/common:grpc_util",
        "//src/ray/common:id",
        "//src/ray/common:memory_monitor",
        "//src/ray/common:network",
        "//src/ray/common:ray_config",
        "//src/ray/common:ray_syncer",
        "//src/ray/common:status",
        "//src/ray/common:task_common",
        "//src/ray/common:test_util",
        "//src/ray/protobuf:gcs_cc_proto",
        "@com_google_googletest//:gtest",
    ],
)

plasma_fbs [done]

代码文件
src/ray/object_manager/plasma/plasma.fbs
无依赖库

其它

        "//src/ray/protobuf:common_cc_proto",
        "//src/ray/util",

Ray编译运行demo

编译

经过6个多小时的奋战,./build.sh终于编译成功,其实回过头来只有两件事情:

  • 安装bazel6.5
  • 安装gcc-9

官网参考:https://docs.ray.io/en/latest/ray-contribute/development.html

下载源代码,然后在根目录下执行 ./build.sh

(pytorch_gpu) ➜  /mnt/c/workspace/llm/ray ./build.sh
  • 报错说,找不到’/root/bin/bazel’,于是参照下面的编译问题来安装 bazel,要求安装bazel6.5版本。
  • 进一步执行./build.sh报错说 pack 不是class template,需要升级到c++17,升级g++到9
  • 切换思路,决策使用小模块编译方案,只编译特定模块,找到根目录的BUILD.bazel文件/mnt/c/workspace/llm/ray/cpp/BUILD.bazel,执行编译grpc lib
    • 编译grpc:在ray源代码的根目录下执行,bazel build //:grpc_common_lib
      在这里插入图片描述
      报错:error: unused variable ‘tag_key’ [-Werror=unused-variable]
  • 重新编译,启用copt参数: bazel build //:grpc_common_lib --copt=-Wno-error=unused-variable。报错:main/test-filesystem.cc:2:10: fatal error: filesystem: No such file or directory #include <filesystem>。 同样需要安装gcc-9
  • 安装g+±9
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
apt install gcc-9 ## 自动安装gcc-9和g++-9
  • 替换默认的g++ 7.5.0
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 50

然后输入g++ --version 可以看到变成9.4.0版本

其它命令
update-alternatives --query g++
update-alternatives --list gcc
sudo update-alternatives --config gcc

bazel info cxx # 查看当前bazel是否使用的g++-9

运行单个目录,更容易缩小问题范围
bazel build //cpp:ray_cpp_pkg --verbose_failures

./build.sh还失败,程序被莫名杀死,dmesg查看内存不足导致,调整机器提供给WSL的内存,直接搜索 wsl 即可进行设置内存,内存设置完毕最终编译成功
在这里插入图片描述

安装

安装nvm

curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash  
nvm install 14
nvm use 14

编译dashboard

cd python/ray/dashboard/client
npm ci
npm run build
cd ../..

安装ray

# Install Ray.
cd python/
# Install required dependencies.
pip install -r requirements.txt
# You may need to set the following two env vars if you have a macOS ARM64(M1) platform.
# See https://github.com/grpc/grpc/issues/25082 for more details.
# export GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1
# export GRPC_PYTHON_BUILD_SYSTEM_ZLIB=1
pip install -e . --verbose  # Add --user if you see a permission denied error.

命令 pip install -e . --verbose 是一个用于安装当前目录下 Python 包的命令

  • -e (可编辑模式):以“可编辑模式”安装当前目录下的 Python 包。这意味着,包的源代码不会被复制到 Python 的 site-packages 目录,而是创建一个指向当前目录的符号链接。
    适用于开发环境,当你对代码进行修改时,这些修改会立即反映在安装的包中。
  • . : 表示安装当前目录下的包,当前目录应该包含 setup.py 文件或 pyproject.toml 文件,以指定包的构建和安装配置

在这里插入图片描述
验证ray
python3 -c "import ray"

如何查看当前目录的ray包

如果你已经以开发模式安装了当前目录的包,可以用 pip list 查看安装的包:
pip list | grep ray,还有一个是 pip show ray
在这里插入图片描述

如果当前目录包含 setup.py,可以执行以下命令来查看定义的包名称:
python setup.py --name

site-packages中有指向ray包的软链接
cat /root/anaconda3/envs/pytorch_gpu/lib/python3.11/site-packages/ray.egg-link
在这里插入图片描述

bazel build基础教程

bazel build //main:hello-world

  • 在当前目录下从项目根目录的 main 子目录开始查找。:hello-world表示 main 目录下的一个构建目标,在main目录下有对应的 BUILD 文件定义。

  • bazel build:
    命令告诉 Bazel 构建指定目标。
    构建结果通常存放在 bazel-out/ 目录下。

教程链接:https://bazel.build/reference/be/c-cpp?hl=zh-cn

生成wheel并测试

组装轮子

cd ~/ray/python
python3 setup.py bdist_wheel

那么最终的轮子就在~/ray/python/dist里了

安装轮子:

cd dist
pip3 install *.whl

测试模块是否工作正常:

cd ~/ray
python3 -m pytest -v python/ray/tests/test_mini.py

编译问题

执行编译期间遇到了很多问题,一一解决

安装 bazel

问题1: FileNotFoundError: [Errno 2] No such file or directory: ‘/root/bin/bazel’
查看bazel的安装文档: https://bazel.build/install/ubuntu?hl=zh-cn
安装bazel

sudo apt install apt-transport-https curl gnupg -y
curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor >bazel-archive-keyring.gpg
  本句的替换: wget https://bazel.build/bazel-release.pub.gpg -O bazel-release.pub.gpg  
                       gpg --dearmor -o bazel-archive-keyring.gpg bazel-release.pub.gpg
sudo mv bazel-archive-keyring.gpg /usr/share/keyrings
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list

sudo apt update && sudo apt install bazel -y
安装bazel 6.5.0

ERROR: The project you’re trying to build requires Bazel 6.5.0 (specified in /mnt/c/workspace/llm/ray/.bazelversion), but it wasn’t found in /usr/bin.

You can install the required Bazel version via apt:

  sudo apt update && sudo apt install bazel-6.5.0
报错 pack不是class template

需要使用c++17编译

ray_cpp_lib/ray/api/msgpack_adaptor.h:27:8: error: 'pack' is not a class template
     struct pack<std::any> {
报错:error: unused variable ‘tag_key’ [-Werror=unused-variable]

重新编译,启用copt参数: bazel build //:grpc_common_lib --copt=-Wno-error=unused-variable

报错:main/test-filesystem.cc:2:10: fatal error: filesystem: No such file or directory #include

安装gcc 9

报错:sed: cannot rename python/ray/serve/generated/sedEFwvtV: Permission denied

sudo chmod -R u+w python/ray/serve/generated/

Ray

设计哲学

不需要将o1以及o2的数据返回给Driver层,只提前设计好框架,数据在workers之间自动按需流转
在这里插入图片描述

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

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

相关文章

开源动态表单form-create-designer 扩展个性化配置的最佳实践教程

在开源低代码表单设计器 form-create-designer 的右侧配置面板里&#xff0c;field 映射规则为开发者提供了强大的工具去自定义和增强组件及表单配置的显示方式。通过这些规则&#xff0c;你可以简单而高效地调整配置项的展示&#xff0c;提升用户体验。 源码地址: Github | G…

美创科技入选2024数字政府解决方案提供商TOP100!

11月19日&#xff0c;国内专业咨询机构DBC德本咨询发布“2024数字政府解决方案提供商TOP100”榜单。美创科技凭借在政府数据安全领域多年的项目经验、技术优势与创新能力&#xff0c;入选收录。 作为专业数据安全产品与服务提供商&#xff0c;美创科技一直致力于为政府、金融、…

地平线 bev_cft_efficientnetb3 参考算法-v1.2.1

01 概述 在自动驾驶感知算法中 BEV 感知成为热点话题&#xff0c;BEV 感知可以弥补 2D 感知的缺陷构建 3D “世界”&#xff0c;更有利于下游任务和特征融合。 地平线集成了基于 bev 的纯视觉算法&#xff0c;目前已支持 ipm-based 、lss-based、 transformer-based&#xff…

C#里怎么样检测文件的属性?

C#里怎么样检测文件的属性? 对于文件来说,在C#里有一种快速的方法来检查文件的属性。 比如文件是否已经压缩, 文件是否加密, 文件是否是目录等等。 属性有下面这么多: 例子演示如下: /** C# Program to View the Information of the File*/ using System; using Syste…

最新‌VSCode保姆级安装教程(附安装包)

文章目录 一、VSCode介绍 二、VSCode下载 下载链接&#xff1a;https://pan.quark.cn/s/19a303ff81fc 三、VSCode安装 1.解压安装文件&#xff1a;双击打开并安装VSCode 2.勾选我同意协议&#xff1a;然后点击下一步 3.选择目标位置&#xff1a;点击浏览 4.选择D盘安装…

传输控制协议(TCP)和用户数据报协议(UDP)

一、传输控制协议&#xff08;TCP&#xff09; 传输控制协议&#xff08;Transmission Control Protocol&#xff0c;TCP&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议&#xff0c;由 IETF 的 RFC 793 定义。 它通过三次握手建立连接&#xff0c;确保数…

linux从0到1——shell编程9

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

nature communications论文 解读

题目《Transfer learning with graph neural networks for improved molecular property prediction in the multi-fidelity setting》 这篇文章主要讨论了如何在多保真数据环境&#xff08;multi-fidelity setting&#xff09;下&#xff0c;利用图神经网络&#xff08;GNNs&…

基于Qt/C++/Opencv实现的一个视频中二维码解析软件

本文详细讲解了如何利用 Qt 和 OpenCV 实现一个可从视频和图片中检测二维码的软件。代码实现了视频解码、多线程处理和界面更新等功能&#xff0c;是一个典型的跨线程图像处理项目。以下分模块对代码进行解析。 一、项目的整体结构 项目分为以下几部分&#xff1a; 主窗口 (M…

【Elasticsearch入门到落地】2、正向索引和倒排索引

接上篇《1、初识Elasticsearch》 上一篇我们学习了什么是Elasticsearch&#xff0c;以及Elastic stack(ELK)技术栈介绍。本篇我们来什么是正向索引和倒排索引&#xff0c;这是了解Elasticsearch底层架构的核心。 上一篇我们学习到&#xff0c;Elasticsearch的底层是由Lucene实…

鸿蒙主流路由详解

鸿蒙主流路由详解 Navigation Navigation更适合于一次开发,多端部署,也是官方主流推荐的一种路由控制方式,但是,使用起来入侵耦合度高,所以,一般会使用HMRouter,这也是官方主流推荐的路由 Navigation官网地址 个人源码地址 路由跳转 第一步-定义路由栈 Provide(PageInfo) pag…

java使用itext生成pdf

一、利用Adobe Acrobat DC软件创建pdf模板 备好Adobe Acrobat DC软件 1.excel/jpg/png文件转pdf文件 右击打开我们要转换的文件 2.然后点击 添加 域 3.可以看到域的名字 4.调整字体大小/对齐方式等 5.保存 二&#xff0c;代码部分 首先 上依赖 <dependency><group…

生成对抗网络模拟缺失数据,辅助PAMAP2数据集仿真实验

PAMAP2数据集是一个包含丰富身体活动信息的数据集&#xff0c;它为我们提供了一个理想的平台来开发和测试HAR模型。本文将从数据集的基本介绍开始&#xff0c;逐步引导大家通过数据分割、预处理、模型训练&#xff0c;到最终的性能评估&#xff0c;在接下来的章节中&#xff0c…

全面解析:HTML页面的加载全过程(一)--输入URL地址,与服务器建立连接

用户输入URL地址&#xff0c;与服务器建立连接 用户在浏览器地址栏输入一个URL 浏览器开始执行以下三步操作操作&#xff1a;url解析、DNS查询、TCP连接 第一步&#xff1a;URL解析 什么是URL&#xff1f; URL(Uniform Resource Locator&#xff0c;统一资源定位符)是互联网…

STM32总体架构简单介绍

目录 一、引言 二、STM32的总体架构 1、三个被动单元 &#xff08;1&#xff09;内部SRAM &#xff08;2&#xff09;内部闪存存储器 &#xff08;3&#xff09;AHB到APB的桥&#xff08;AHB to APBx&#xff09; 2、四个主动&#xff08;驱动&#xff09;单元 &#x…

postman 调用 下载接口(download)使用默认名称(response.txt 或随机名称)

官网地址&#xff1a;https://www.postman.com 介绍 Postman 是一款流行的 API 开发和测试工具&#xff0c;用于发送 HTTP 请求、测试接口、调试服务器响应以及进行 API 文档管理。它支持多种请求类型&#xff08;如 GET、POST、PUT、DELETE 等&#xff09;&#xff0c;并且功能…

JavaScript将至

JS是什么&#xff1f; 是一种运行在客户端&#xff08;浏览器&#xff09;的编程语言&#xff0c;实现人机交互效果 作用捏&#xff1f; 网页特效 (监听用户的一些行为让网页作出对应的反馈) 表单验证 (针对表单数据的合法性进行判断) 数据交互 (获取后台的数据, 渲染到前…

Vue.js 学习总结(13)—— Vue3 version 计数介绍

前言 Vue3.5 提出了两个重要概念&#xff1a;version计数和双向链表&#xff0c;作为在内存和计算方面性能提升的最大功臣。既然都重要&#xff0c;那就单挑 version 计数来介绍&#xff0c;它在依赖追踪过程中&#xff0c;起到快速判断依赖项有没有更新的作用&#xff0c;所以…

全面解析多种mfc140u.dll丢失的解决方法,五种方法详细解决

当你满心期待地打开某个常用软件&#xff0c;却突然弹出一个错误框&#xff0c;提示“mfc140u.dll丢失”&#xff0c;那一刻&#xff0c;你的好心情可能瞬间消失。这种情况在很多电脑用户的使用过程中都可能出现。无论是游戏玩家还是办公族&#xff0c;面对这个问题都可能不知所…

《Spring 实战:小型项目开发初体验》

一、引言 Spring 作为一款强大的 Java 开发框架&#xff0c;在小型项目开发中有着广泛的应用。本文将带你深入体验 Spring 在小型项目开发中的实战过程&#xff0c;从环境搭建到项目部署&#xff0c;全面展示 Spring 的魅力。 一、引言 Spring 作为一款强大的 Java 开发框架&…