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

【机器学习】与【数据挖掘】技术下【C++】驱动的【嵌入式】智能系统优化

ecde6503e5cb4996a0ff258b3d1ffc28.png

目录

一、嵌入式系统简介

二、C++在嵌入式系统中的优势

三、机器学习在嵌入式系统中的挑战

四、C++实现机器学习模型的基本步骤

五、实例分析:使用C++在嵌入式系统中实现手写数字识别

1. 数据准备

2. 模型训练与压缩

3. 模型部署

六、优化与分析

1. 模型优化

模型量化

模型剪枝

2. 系统优化

内存管理

计算资源分配

电源管理

七、性能评估与优化策略

1. 性能评估指标

2. 性能优化策略

八、实际应用案例 -嵌入式图像分类系统

概述

步骤

1. 数据准备

2. 模型部署

3. 实时推理

九、总结与展望


63748e72dc314943857316f3b1f6a386.gif#pic_center

随着物联网(IoT)和智能设备的普及,嵌入式系统变得越来越重要。而随着人工智能(AI)和机器学习(ML)技术的发展,将这些技术应用于嵌入式系统中可以实现许多智能应用,如智能家居、自动驾驶和工业自动化等。然而,由于嵌入式系统的资源有限,将AI和ML应用到嵌入式系统中面临许多挑战。

一、嵌入式系统简介

a75256bf614b4ba68d12d5f6ad533168.png

嵌入式系统是一种专用计算机系统,通常嵌入到大型系统中,执行特定任务。典型的嵌入式系统包括微控制器(MCU)、单板计算机(SBC)和专用AI加速器。嵌入式系统的主要特点包括:

  • 资源受限:CPU、内存和存储资源较少。
  • 实时性要求:需要在严格的时间限制内完成任务。
  • 专用性强:专为特定任务或设备设计。

二、C++在嵌入式系统中的优势

C++因其高效性和面向对象的特性,在嵌入式系统中得到了广泛应用。其优势包括:

  • 高性能:C++的编译后代码执行效率高,适合资源受限的嵌入式系统。
  • 面向对象:便于代码模块化和重用。
  • 丰富的库支持:标准库和第三方库丰富,便于实现复杂功能。

三、机器学习在嵌入式系统中的挑战

将机器学习模型部署到嵌入式系统中需要克服多种挑战:

  • 模型压缩:减少模型的大小和计算复杂度。
  • 实时性:确保模型推理的实时响应。
  • 资源管理:优化内存和计算资源的使用。

四、C++实现机器学习模型的基本步骤

  1. 数据准备:获取并预处理数据。
  2. 模型训练:在PC或服务器上训练模型。
  3. 模型压缩:使用量化、剪枝等技术压缩模型。
  4. 模型部署:将模型移植到嵌入式系统中。
  5. 实时推理:在嵌入式设备上进行实时推理。

五、实例分析:使用C++在嵌入式系统中实现手写数字识别

以下实例将展示如何在嵌入式系统中使用C++和TensorFlow Lite实现手写数字识别。

c1e2a01d6f8549498683cd2f261d7e47.png

1. 数据准备

我们使用MNIST数据集进行手写数字识别。首先,需要将数据集转换为适合嵌入式系统使用的格式。

#include <fstream>
#include <vector>
#include <iostream>void read_mnist(const std::string &filename, std::vector<std::vector<uint8_t>> &images) {std::ifstream file(filename, std::ios::binary);if (file.is_open()) {int magic_number = 0;int number_of_images = 0;int rows = 0;int cols = 0;file.read((char*)&magic_number, sizeof(magic_number));magic_number = __builtin_bswap32(magic_number);file.read((char*)&number_of_images, sizeof(number_of_images));number_of_images = __builtin_bswap32(number_of_images);file.read((char*)&rows, sizeof(rows));rows = __builtin_bswap32(rows);file.read((char*)&cols, sizeof(cols));cols = __builtin_bswap32(cols);for (int i = 0; i < number_of_images; ++i) {std::vector<uint8_t> image(rows * cols);file.read((char*)image.data(), rows * cols);images.push_back(image);}}
}

2. 模型训练与压缩

在PC上使用Python和TensorFlow训练一个简单的卷积神经网络(CNN)模型,并将其转换为适合嵌入式系统的格式。

import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten
import numpy as np# 加载数据集
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0# 构建模型
model = Sequential([Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(28, 28, 1)),Flatten(),Dense(128, activation='relu'),Dense(10, activation='softmax')
])# 编译和训练模型
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)# 模型量化
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()# 保存模型
with open('model.tflite', 'wb') as f:f.write(tflite_model)

3. 模型部署

使用TensorFlow Lite将模型部署到嵌入式系统中,并进行推理。

#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/kernels/register_ref.h"
#include <vector>
#include <iostream>void run_inference(const std::vector<uint8_t> &input_image) {// 加载模型const char* model_path = "model.tflite";auto model = tflite::FlatBufferModel::BuildFromFile(model_path);tflite::ops::builtin::BuiltinOpResolver resolver;std::unique_ptr<tflite::Interpreter> interpreter;tflite::InterpreterBuilder(*model, resolver)(&interpreter);// 分配张量interpreter->AllocateTensors();int input = interpreter->inputs()[0];uint8_t* input_data = interpreter->typed_tensor<uint8_t>(input);// 将图像数据复制到输入张量std::copy(input_image.begin(), input_image.end(), input_data);// 运行推理interpreter->Invoke();// 获取输出int output = interpreter->outputs()[0];float* output_data = interpreter->typed_tensor<float>(output);// 打印结果for (int i = 0; i < 10; ++i) {std::cout << "Probability of " << i << ": " << output_data[i] << std::endl;}
}

六、优化与分析

在实际应用中,我们需要不断优化模型和系统,以满足嵌入式设备的资源限制和性能需求。以下是一些常见的优化策略和分析方法。

1. 模型优化

模型优化可以通过多种方式进行,包括量化、剪枝和知识蒸馏。

模型量化

模型量化可以显著减少模型的大小和计算量,提高推理速度。

# 模型量化
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
quantized_model = converter.convert()# 保存量化后的模型
with open('quantized_model.tflite', 'wb') as f:f.write(quantized_model)

模型剪枝

模型剪枝可以通过删除不重要的权重来减少模型的大小。

import tensorflow_model_optimization as tfmot# 定义剪枝参数
pruning_params = {'pruning_schedule': tfmot.sparsity.keras.PolynomialDecay(initial_sparsity=0.50,final_sparsity=0.90,begin_step=0,end_step=1000)
}# 使用剪枝API
model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(model, **pruning_params)# 编译模型
model_for_pruning.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])# 训练模型
model_for_pruning.fit(x_train, y_train, epochs=2, validation_data=(x_test, y_test))# 删除剪枝标记并保存模型
model_for_export = tfmot.sparsity.keras.strip_pruning(model_for_pruning)
model_for_export.save('pruned_model.h5')

2. 系统优化

在嵌入式系统中,除了优化模型外,还需要优化系统的各个方面,包括内存管理、计算资源分配和电源管理。

内存管理

在嵌入式系统中,内存资源通常非常有限,因此高效的内存管理是至关重要的。

// 示例代码:高效内存管理
#include <vector>
#include <iostream>// 使用内存池管理动态内存分配
class MemoryPool {
public:MemoryPool(size_t size) : size_(size), memory_(new char[size]), offset_(0) {}~MemoryPool() {delete[] memory_;}void* allocate(size_t size) {if (offset_ + size > size_) {throw std::bad_alloc();}void* ptr = memory_ + offset_;offset_ += size;return ptr;}void deallocate(void* ptr, size_t size) {// 简单实现,不做实际操作}private:size_t size_;char* memory_;size_t offset_;
};// 示例使用
int main() {MemoryPool pool(1024);int* a = static_cast<int*>(pool.allocate(sizeof(int) * 10));for (int i = 0; i < 10; ++i) {a[i] = i;std::cout << a[i] << " ";}std::cout << std::endl;pool.deallocate(a, sizeof(int) * 10);return 0;
}

计算资源分配

在多核嵌入式系统中,可以使用并行计算来提高模型推理的速度。

// 示例代码:多线程并行计算
#include <thread>
#include <vector>
#include <iostream>void process_data(int id, const std::vector<int>& data) {for (auto val : data) {std::cout << "Thread " << id << ": " << val << std::endl;}
}int main() {std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};std::thread t1(process_data, 1, std::ref(data));std::thread t2(process_data, 2, std::ref(data));t1.join();t2.join();return 0;
}

电源管理

在电池供电的嵌入式系统中,电源管理至关重要。可以通过动态电压和频率调节(DVFS)来降低功耗。

// 示例代码:电源管理(伪代码)
#include <iostream>void adjust_frequency(int level) {// 根据需要调整CPU频率std::cout << "Adjusting CPU frequency to level: " << level << std::endl;
}int main() {int workload = 50; // 示例工作负载if (workload < 20) {adjust_frequency(1); // 低频率} else if (workload < 70) {adjust_frequency(2); // 中等频率} else {adjust_frequency(3); // 高频率}return 0;
}

七、性能评估与优化策略

评估和优化模型在嵌入式系统上的性能是确保系统能够满足实际应用需求的重要步骤。

1. 性能评估指标

  • 推理时间:模型从输入到输出的时间。
  • 内存使用:模型运行时的内存占用。
  • 能耗:模型运行时的功耗。

2. 性能优化策略

  • 使用硬件加速:利用硬件平台的AI加速器。
  • 优化编译器:使用针对特定硬件优化的编译器和库,如TensorFlow Lite Micro。
  • 并行处理:在多核系统中使用并行计算提高推理速度。

八、实际应用案例 -嵌入式图像分类系统

4df95d93e16647e78fff05e95b201ece.png

构建一个嵌入式图像分类系统,使用Raspberry Pi和TensorFlow Lite进行实时图像分类。

概述

在本案例中,我们将使用Raspberry Pi和TensorFlow Lite部署一个手写数字识别模型。本文将详细展示如何在嵌入式系统中实现图像分类的每一步,包括数据准备、模型部署和实时推理。

步骤

  1. 数据准备:获取MNIST数据集并转换为适合嵌入式系统使用的格式。
  2. 模型训练与量化:使用预训练的TensorFlow Lite模型。
  3. 模型部署:将模型部署到Raspberry Pi上。
  4. 实时推理:在Raspberry Pi上进行实时图像分类。

1. 数据准备

在C++中读取MNIST数据集,并将其格式化为适合模型输入的形式。

#include <iostream>
#include <fstream>
#include <vector>void read_mnist(const std::string &filename, std::vector<std::vector<uint8_t>> &images) {std::ifstream file(filename, std::ios::binary);if (file.is_open()) {int magic_number = 0;int number_of_images = 0;int rows = 0;int cols = 0;file.read((char*)&magic_number, sizeof(magic_number));magic_number = __builtin_bswap32(magic_number);file.read((char*)&number_of_images, sizeof(number_of_images));number_of_images = __builtin_bswap32(number_of_images);file.read((char*)&rows, sizeof(rows));rows = __builtin_bswap32(rows);file.read((char*)&cols, sizeof(cols));cols = __builtin_bswap32(cols);for (int i = 0; i < number_of_images; ++i) {std::vector<uint8_t> image(rows * cols);file.read((char*)image.data(), rows * cols);images.push_back(image);}}
}int main() {std::vector<std::vector<uint8_t>> images;read_mnist("train-images-idx3-ubyte", images);std::cout << "Read " << images.size() << " images." << std::endl;return 0;
}

2. 模型部署

使用TensorFlow Lite的C++ API将量化后的模型部署到Raspberry Pi上。

#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/interpreter.h"
#include <vector>
#include <iostream>
#include <memory>void run_inference(const std::vector<uint8_t> &input_image) {// 加载模型const char* model_path = "model.tflite";auto model = tflite::FlatBufferModel::BuildFromFile(model_path);tflite::ops::builtin::BuiltinOpResolver resolver;std::unique_ptr<tflite::Interpreter> interpreter;tflite::InterpreterBuilder(*model, resolver)(&interpreter);// 分配张量interpreter->AllocateTensors();int input = interpreter->inputs()[0];uint8_t* input_data = interpreter->typed_tensor<uint8_t>(input);// 将图像数据复制到输入张量std::copy(input_image.begin(), input_image.end(), input_data);// 运行推理interpreter->Invoke();// 获取输出int output = interpreter->outputs()[0];float* output_data = interpreter->typed_tensor<float>(output);// 打印结果for (int i = 0; i < 10; ++i) {std::cout << "Probability of " << i << ": " << output_data[i] << std::endl;}
}int main() {std::vector<uint8_t> image_data(28 * 28); // 假设我们有一个28x28的灰度图像数据// 在此处加载图像数据run_inference(image_data);return 0;
}

 

3. 实时推理

在Raspberry Pi上进行实时推理,需要处理实时获取的图像数据并进行推理。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/model.h"void preprocess_image(const cv::Mat &image, std::vector<uint8_t> &output_image) {cv::Mat resized_image;cv::resize(image, resized_image, cv::Size(28, 28));cv::cvtColor(resized_image, resized_image, cv::COLOR_BGR2GRAY);output_image.assign(resized_image.data, resized_image.data + resized_image.total());
}void classify_image(const std::vector<uint8_t> &image_data) {const char* model_path = "model.tflite";auto model = tflite::FlatBufferModel::BuildFromFile(model_path);tflite::ops::builtin::BuiltinOpResolver resolver;std::unique_ptr<tflite::Interpreter> interpreter;tflite::InterpreterBuilder(*model, resolver)(&interpreter);interpreter->AllocateTensors();int input_index = interpreter->inputs()[0];uint8_t* input_data = interpreter->typed_tensor<uint8_t>(input_index);std::copy(image_data.begin(), image_data.end(), input_data);interpreter->Invoke();int output_index = interpreter->outputs()[0];float* output_data = interpreter->typed_tensor<float>(output_index);for (int i = 0; i < 10; ++i) {std::cout << "Class " << i << ": " << output_data[i] << std::endl;}
}int main() {cv::VideoCapture cap(0);if (!cap.isOpened()) {std::cerr << "Error opening video stream" << std::endl;return -1;}while (true) {cv::Mat frame;cap >> frame;if (frame.empty()) {break;}std::vector<uint8_t> image_data;preprocess_image(frame, image_data);classify_image(image_data);cv::imshow("Frame", frame);if (cv::waitKey(10) == 27) {break;}}cap.release();cv::destroyAllWindows();return 0;
}

九、总结与展望

在嵌入式系统中使用C++进行机器学习和数据挖掘,包括数据准备、模型训练与压缩、模型部署以及实时推理。未来,随着硬件和算法的不断进步,嵌入式机器学习将会有更加广阔的应用前景,推动物联网、智能制造和智能家居等领域的创新发展。

d6f8de9bc53d443f9b9584c9760c1871.png

 

 

 

相关文章:

【机器学习】与【数据挖掘】技术下【C++】驱动的【嵌入式】智能系统优化

目录 一、嵌入式系统简介 二、C在嵌入式系统中的优势 三、机器学习在嵌入式系统中的挑战 四、C实现机器学习模型的基本步骤 五、实例分析&#xff1a;使用C在嵌入式系统中实现手写数字识别 1. 数据准备 2. 模型训练与压缩 3. 模型部署 六、优化与分析 1. 模型优化 模…...

Apollo9.0 PNC源码学习之Control模块(二)

前面文章&#xff1a;Apollo9.0 PNC源码学习之Control模块&#xff08;一&#xff09; 本文将对具体控制器以及原理做一个剖析 1 PID控制器 1.1 PID理论基础 如下图所示&#xff0c;PID各参数(Kp,Ki,Kd)的作用&#xff1a; 任何闭环控制系统的首要任务是要稳、准、快的响…...

直线度测量仪发展历程!

直线度测量仪的发展历程可以概括为以下几个关键阶段&#xff1a; 拉钢丝法&#xff1a; 早期直线度测量的简单直观方法&#xff0c;利用钢丝受重力自然下垂的原理来测量直线度误差。 随着机械设备的大型化和测量精度要求的提高&#xff0c;该方法逐渐无法满足要求&#xff0c;正…...

09-spring的bean创建流程(一)

文章目录 spring中bean的创建流程finishBeanFactoryInitialization(beanFactory)beanFactory.preInstantiateSingletons();getMergedLocalBeanDefinition(beanName);流程实现FactoryBean接口,里面的对象实例化过程 spring中bean的创建流程 finishBeanFactoryInitialization(be…...

spring中基于setting和构造器的注入方式

Spring中可以通过setting和构造器两种方式进行依赖注入。 1.基于setting的注入方式&#xff08;Setter Injection&#xff09;: 实现方式&#xff1a;在类中添加对应的属性以及对应的setter方法&#xff0c;在配置文件中使用<property>元素进行注入。 示例代码&#xf…...

爬虫基本原理?介绍|实现|问题解决

爬虫基本原理&#xff1a; 模拟用户行为&#xff1a; 网络爬虫&#xff08;Web Crawler&#xff09;是一种自动化的程序&#xff0c;它模拟人类用户访问网站的方式&#xff0c;通过发送HTTP/HTTPS请求到服务器以获取网页内容。 请求与响应&#xff1a; 爬虫首先构建并发送带有…...

DevOps的原理及应用详解(六)

本系列文章简介&#xff1a; 在当今快速变化的商业环境中&#xff0c;企业对于软件交付的速度、质量和安全性要求日益提高。传统的软件开发和运维模式已经难以满足这些需求&#xff0c;因此&#xff0c;DevOps&#xff08;Development和Operations的组合&#xff09;应运而生&a…...

手撸 串口交互命令行 及 AT应用层协议解析框架

在嵌入式系统开发中&#xff0c;命令行接口&#xff08;CLI&#xff09;和AT命令解析是常见的需求。CLI提供了方便的调试接口&#xff0c;而AT命令则常用于模块间的通信控制。本文将介绍如何手动实现一个串口交互的命令行及AT应用层协议解析框架&#xff0c;适用于FreeRTOS系统…...

Redis几种部署模式介绍

Redis 提供了几种不同的部署模式&#xff0c;以满足不同的使用场景和可用性需求。这些模式包括单机模式、主从复制、哨兵模式和集群模式。下面我将简要介绍每种模式的特点和用途&#xff1a; 单机模式&#xff1a; 描述&#xff1a;单个 Redis 服务器实例运行在一台机器上&…...

【STM32HAL库学习】定时器功能、时钟以及各种模式理解

一、文章目的 记录自己从学习了定时器理论->代码实现使用定时->查询数据手册&#xff0c;加深了对定时器的理解以及该过程遇到了的一些不清楚的知识。 上图为参考手册里通用定时器框图&#xff0c;关于定时器各种情况的工作都在上面了&#xff0c;在理论学习和实际应用后…...

3588麒麟系统硬解码实战

目录 安装rockchip-mpp deb 查找头文件 .pro文件添加 检查库是否已安装 error: stdlib.h: No such file or directory ffmpeg 查找ffmpeg路径: 查找FFmpeg库和头文件的位置 使用pkg-config工具查找FFmpeg路径 ok的ffmpeg配置: ffmpeg查看是否支持libx264 ffmpeg …...

十二 nginx中location重写和匹配规则

十二 location匹配规则 ^~ ~ ~* !~ !~* /a / 内部服务跳转 十三 nginx地址重写rewrite if rewrite set return 13.1 if 应用环境 server location -x 文件是否可执行 $args $document_rot $host $limit_rate $remote_addr $server_name $document_uri if …...

python的视频处理FFmpeg库使用

FFmpeg 是一个强大的多媒体处理工具,用于录制、转换和流式传输音频和视频。它支持几乎所有的音频和视频格式,并且可以在各种平台上运行。FFmpeg 在 Python 中的使用可以通过调用其命令行工具或使用专门的库如 ffmpeg-python。以下是详细介绍如何在 Python 中使用 FFmpeg,包括…...

接口测试时, 数据Mock为何如此重要?

一、为什么要mock 工作中遇到以下问题&#xff0c;我们可以使用mock解决&#xff1a; 1、无法控制第三方系统某接口的返回&#xff0c;返回的数据不满足要求 2、某依赖系统还未开发完成&#xff0c;就需要对被测系统进行测试 3、有些系统不支持重复请求&#xff0c;或有访问…...

未授权与绕过漏洞

1、Laravel Framework 11 - Credential Leakage&#xff08;CVE-2024-29291&#xff09;认证泄漏 导航这个路径storage/logs/laravel.log搜索以下信息&#xff1a; PDO->__construct(mysql:host 2、 Flowise 1.6.5 - Authentication Bypass&#xff08;CVE-2024-31621&am…...

云原生周刊:Kubernetes 十周年 | 2024.6.11

开源项目推荐 Kubernetes Goat Kubernetes Goat 是一个故意设计成有漏洞的 Kubernetes 集群环境&#xff0c;旨在通过交互式实践场地来学习并练习 Kubernetes 安全性。 kube-state-metrics (KSM) kube-state-metrics 是一个用于收集 Kubernetes 集群状态信息的开源项目&…...

ClickHouse内幕(1)数据存储与过滤机制

本文主要讲述ClickHouse中的数据存储结构&#xff0c;包括文件组织结构和索引结构&#xff0c;以及建立在其基础上的数据过滤机制&#xff0c;从Part裁剪到Mark裁剪&#xff0c;最后到基于SIMD的行过滤机制。 数据过滤机制实质上是构建在数据存储格式之上的算法&#xff0c;所…...

1.Mongodb 介绍及部署

MongoDB 是一个开源的文档导向数据库&#xff0c;采用NoSQL&#xff08;非关系型数据库&#xff09;的设计理念。MongoDB是一个基于分布式文件存储的数据库。 分布式文件存储是一种将文件数据分布式的存储在多台计算机上。MongoDB是一款强大的文档导向数据库&#xff0c;适合处…...

Java 技巧:如何获取字符串中最后一个英文逗号后面的内容

在日常的Java编程中&#xff0c;处理字符串是非常常见的任务之一。有时我们需要从一个字符串中截取特定部分&#xff0c;例如获取最后一个英文逗号后的内容。这篇文章将详细介绍如何使用Java来实现这一需求&#xff0c;并提供一个示例代码来演示其实现过程。 需求分析 假设我们…...

玩转微服务-GateWay

目录 一. 背景二. API网关1. 概念2. API网关定义3. API网关的四大职能4. API网关分类5. 开源API网关介绍6. 开源网关的选择 三. Spring Cloud Gateway1. 文档地址2. 三个核心概念3. 工作流程4. 运行原理4.1 路由原理4.2 RouteLocator 5. Predicate 断言6. 过滤器 Filter6.1. 过…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...