041_Compare_Matrix_Squre_Sum_in_MATLAB中矩阵平方和的比较
矩阵平方和的计算
矩阵平方和的定义
矩阵平方和的定义是对矩阵中的每一个元素进行平方,然后求和。
对于一个矩阵 A A A,其平方和定义为:
sum = ∑ i = 1 m ∑ j = 1 n A ( i , j ) 2 \text{sum} = \sum_{i=1}^{m}\sum_{j=1}^{n} A(i,j)^2 sum=i=1∑mj=1∑nA(i,j)2
这个平方和计算,在某些机器学习的算法中、或者特殊的优化问题中都会涉及到。
矩阵平方和的计算方法
通常而言,前面的公式就给出了计算的方法,无论怎么做,都会涉及到对矩阵中的每一个元素进行平方,然后求和。
因此算法的时间复杂度是 O ( m ∗ n ) O(m*n) O(m∗n),其中 m m m是矩阵的行数, n n n是矩阵的列数,当 A A A是方阵时, m = n m=n m=n。
最终,算法的效率取决于矩阵的表示形式和对矩阵元素的访问方式。
当然,还有可能会有一些特殊的优化方法,比如矩阵的特殊性质,可以通过一些特殊的方法来计算,这里不做考虑。
最后,就是并行指令集的使用,比如SIMD指令集,这里也不进行相关的讨论。
下面,就主要是对在Matlab中实现矩阵平方和的几种方法进行比较。其实比较的是Matlab中访问矩阵元素的方式的性能差异。
Matlab的若干实现
我们非常随意的实现了一些方法。
其中最重要的就是所谓的基线方法。这个方法通常选择一个最简单/直观的方法,便于抓住算法中的核心要素。
然后作为对比的基准,也能够对不同算法的性能进行比较。
这种研究办法,是一种常见的研究方法。例如,在优化算法中,通常选择格子搜索或者随机搜索作为基线方法。
提出一种新的方法,通常希望能够对比基线方法有更好的性能,并且这种性能提升是显著的。
此外,也会结合新算法与基线算法的执行过程来解释算法优势的原理,这就是一般算法研究文章中非常重要的理论分析。
function sumRet = bench_loop_row_column(A)% 按照行、列的方式进行循环求和,基线算法% 内存:O(1)% 时间:O(m*n) ~ O(n^2)[m, n] = size(A);sumRet = 0;% 对行进行循环for i = 1:m% 对列进行循环for j = 1:nsumRet = sumRet + A(i, j) ^ 2;end% 列循环结束end% 行循环结束,
end
上面这个最为直观的算法,就是对矩阵的每一行进行遍历,然后对每一行的每一个元素进行平方,然后求和。
这个作为基线是一个恰当的选择。
相应的,我们就会想到先循环列,再循环行来作为对基线算法的改进。
function sumRet = bench_loop_column_row(A)% 按照列、行的方式进行循环求和,第一次改进的算法% 充分考虑到矩阵的存储方式:列优先% 内存:O(1)% 时间:O(m*n) ~ O(n^2)[m, n] = size(A);sumRet = 0;for i = 1:nfor j = 1:msumRet = sumRet + A(j, i) ^ 2;endendend
考虑到Matlab能够直接索引列,我们就可以考虑对每列进行循环,直接对列进行操作。或者,换成对行进行操作。
下面几个算法就是行、列操作的形式,这里又有一个小小的差别,就是使用更多内存来直接进行向量加法,最后调用sum
求和。
或者还可以在循环内部调用sum
函数,这样内存的使用会从 O ( n ) \mathcal{O}(n) O(n)降低到
function s = bench_loop_column_sum(A)% 直接循环列,采用向量化的方式访问每个列% 用一个向量来存储每一列和% 最终调用sum函数求和% 内存:O(n)% 时间:考虑到,向量加法的时间复杂度是O(n)% 所以,这里的时间复杂度依然是O(m*n) ~ O(n^2)N = size(A, 2);v = zeros(size(A, 1), 1);for i = 1:Nv = v + A(:, i) .^ 2;ends = sum(v);
end
function s = bench_loop_sum_column(A)% 直接循环列,采用向量化的方式访问每个列% 直接对列调用sum函数求列和,最终累加求和% 内存:O(1)% 时间:O(m*n) ~ O(n^2),这里同样认为.^ 的时间复杂度是O(n)s = 0;N = size(A, 2);for i = 1:Ns = s + sum(A(:, i) .^ 2);endend
function s = bench_loop_row_sum(A)% 直接循环行,采用向量化的方式访问每行% 用一个向量来存储行和% 最终调用sum函数求和% 内存:O(n)% 时间:考虑到,向量加法的时间复杂度是O(n)% 所以,这里的时间复杂度依然是O(m*n) ~ O(n^2)N = size(A, 1);v = zeros(1, size(A, 2));for i = 1:Nv = v + A(i, :) .^ 2;ends = sum(v);
end
function s = bench_loop_sum_row(A)% 直接循环行,采用向量化的方式访问每个行% 直接对行调用sum函数求行和,最终累加求和% 内存:O(1)% 时间:O(m*n) ~ O(n^2),这里同样认为.^ 的时间复杂度是O(n)s = 0;N = size(A, 1);for i = 1:Ns = s + sum(A(i, :) .^ 2);endend
接下来,我们利用矩阵的向量访问方式来构造一个算法。
function s = bench_loop_vec(A)% 直接将矩阵展开成一个向量,循环求和% 内存:O(1)% 时间:O(m*n) ~ O(n^2)s = 0;N = numel(A);for i = 1:Ns = s + A(i) .^ 2;endend
此外,sum
函数也提供了两个算法变体,一个是调用两次(默认对行求和)
function s = bench_sum_sum(A)% 直接两次调用sum函数,对矩阵进行求和s = sum(sum(A .^ 2));
end
function s = bench_sum_all(A)% 直接调用一次sum函数,对矩阵进行求和s = sum(A .^ 2, 'all');
end
还可以把sum
与矩阵列向量访问形式结合起来,构成一种算法。
function s = bench_sum_vec(A)% 直接将矩阵展开成一个向量% 进行元素.^计算,调用sum函数求和s = sum(A(:) .^ 2);
end
最后还是利用矩阵的向量展开方式,就是两个其实一样的算法,因为dot
函数内部就是调用矩阵乘法。
function s = bench_vec_dot(A)% 直接将矩阵展开成一个向量,进行点积计算s = dot(A(:), A(:));
end
function s = bench_matrix_mul(A)% 直接将矩阵展开成一个向量,进行矩阵乘法计算s = A(:).' * A(:);
end
这些算法都非常平常,但是,通过上面的联系,也能提升我们对Matlab的矩阵操作的理解。
接下来就是对这些算法的性能进行比较。
性能比较
性能比较方法
时间性能比较,一般可以直接利用timeit
函数来完成,这个函数会对一个函数进行多次调用,然后求中位数。
这个函数还能包括输出变量的构造时间。
利用这个函数,我们编了一个工具,对不同规模的矩阵进行比较。
这里代码的注释非常清楚,无需赘述。
%% Benchmark functions helper
function [n, result] = bench_f_n(n, f)% 按照给定的参数,对函数进行测试% n: 矩阵大小% f: 函数句柄% 返回值:n, result% n: 矩阵大小的向量, result: 运行时间的向量argumentsn (:, :) {mustBePositive}f function_handleend% 保证n是一个向量,并且是正整数n = round(n(:));result = zeros(1, numel(n));% 对每一个n进行测试,直接采用for循环,不使用arrayfunfor i = 1:numel(n)A = rand(n(i), n(i));result(i) = timeit(@()f(A));end% result = arrayfun(@(x) timeit(@()f(rand(x, x))), n);% 这样也是可以的,但是,对于此处,上面的写法更加直观% 这就是采用for循环的地方% 为了代码的可读性,并且对性能的影响不大,因为这里的循环次数不多
end
性能比较代码
我们把前面的算法代码和上面的性能比较代码放在一个+benchobjs
的目录中,就构成一个namespace命名空间,通过import benchobjs.*
来导入这些函数。
编写如下的测试脚本:
- Matlab code
- 设置测试范围
- 运行测试获取数据
- 可视化测试结果
%% import functions in benchobjs
import benchobjs.*;%% setup problem
n = round(logspace(3, 4, 10));
functions = {@bench_loop_row_column, @bench_loop_column_row, ...@bench_loop_column_sum, @bench_loop_sum_column, ...@bench_loop_row_sum, @bench_loop_sum_row, ...@bench_loop_vec, @bench_sum_sum, ...@bench_sum_all, @bench_sum_vec, ...@bench_vec_dot, @bench_matrix_mul};
markers = {'o', 'x', '+', '*', 's', 'd', '^', 'v', '>', '<', 'p', 'h'};
% 这里是常见的小技巧,将函数的句柄存储在一个cell数组中
% 这样可以方便的对这些函数进行遍历
% 同时,把线型标签也存储在一个cell数组中,这样可以方便的对这些线型进行遍历%% calculation
results = cell(numel(functions), 2);for i = 1:numel(functions)[n, result] = bench_f_n(n, functions{i});results{i, 1} = n;results{i, 2} = result;fprintf('%s: %s: %s\n', func2str(functions{i}), ...mat2str(n), mat2str(result));
endcmd = sprintf('save compareMatrixSquareSum%d results', maxNumCompThreads);
eval(cmd);% 这里试图考虑到多线程的影响,目前在12核心的及其上进行了不同线程数的测试
% 发现对于这个问题,多线程并没有展现出过大的差别
%% Visualize
% 一般也会把原始数据画出来稍微看一下
% 为了确保数据的正确性,并且可以对数据进行初步的分析
figure;
clf;for i = 1:numel(functions)[n, result] = results{i, :};plot(n, result, 'LineWidth', 2, 'Marker', markers{i});yscale('log');hold on;fprintf('%s: %s: %s\n', func2str(functions{i}), ...mat2str(n), mat2str(result));
endlegend(cellfun(@(f)cellref(split(func2str(f), '.'), 2), ...functions, 'UniformOutput', false), ...'Location', 'BestOutSide', "interpreter", "none");
xlabel('Matrix size');
ylabel('Time (s)');
grid on% exportgraphics(gcf, '../matlab-img/compareMatrixSquareSum-time.png', ...
% 'Resolution', 600);%% Visualize 2
% 针对基准的加速比,这是最常见的基准测试结果的展示方式
figure;
clf;for i = 2:numel(functions)[n, result] = results{i, :};plot(n, results{1, 2} ./ result, ...'LineWidth', 2, 'Marker', markers{i});hold on;fprintf('%s: %s: %s\n', func2str(functions{i}), ...mat2str(n), mat2str(result));
endlegend(cellfun(@(f)cellref(split(func2str(f), '.'), 2), ...functions(2:numel(functions)), 'UniformOutput', false), ...'Location', 'BestOutSide', "interpreter", "none");
xlabel('Matrix size');
ylabel('Time (s)');
grid on% exportgraphics(gcf, '../matlab-img/compareMatrixSquareSum-acc.png', ...
% 'Resolution', 600);%% Visualize 2
% 去掉基准和两个最好的函数,这样可以进行更加细节的比较和分析
% 这里必要性不太大,主要是为了展示这种方式
figure;
clf;for i = 2:numel(functions) - 2[n, result] = results{i, :};plot(n, results{1, 2} ./ result, ...'LineWidth', 2, 'Marker', markers{i});hold on;fprintf('%s: %s: %s\n', func2str(functions{i}), ...mat2str(n), mat2str(result));
endlegend(cellfun(@(f)cellref(split(func2str(f), '.'), 2), ...functions(2:numel(functions) - 2), 'UniformOutput', false), ...'Location', 'BestOutSide', "interpreter", "none");
xlabel('Matrix size');
ylabel('Time (s)');
grid on% exportgraphics(gcf, '../matlab-img/compareMatrixSquareSum-acc-2.png',...
% 'Resolution', 600);```
性能比较结果
最终,可以得到如下的性能比较结果。
首先,不同算法的性能有一定差异。基本上,算法分为两组,也可以视为三组。
- 第一组是基线算法,对每一行进行遍历,然后对每一个元素进行平方,然后求和。
- 第二组是向量展开访问并调用矩阵乘法(
mtimes
直接调用BLAS二进制库)的两个算法,性能相当。 - 其他就是各种循环的组合以及
sum
函数的组合。
这个分组,按照加速比来看,更加明显。
向量展开+矩阵乘法的算法在1000~10000的规模下,性能均有显著提升,从15倍到40倍。
除去基线算法和向量化算法,其他算法的关系较为复杂,但是也能通过进行列访问、部分向量化来获得几倍的性能提升。
这充分显示了列优先矩阵访问对与计算效率的影响。
总结
- 进行算法开发,一定要按照基线算法、算法优化的思路来考虑。
- 对算法的效率进行比较,最好选择不同的规模来分析问题。
- 加速比是一个很好的指标,能够直观的看出算法的性能提升。
相关文章:
041_Compare_Matrix_Squre_Sum_in_MATLAB中矩阵平方和的比较
矩阵平方和的计算 矩阵平方和的定义 矩阵平方和的定义是对矩阵中的每一个元素进行平方,然后求和。 对于一个矩阵 A A A,其平方和定义为: sum ∑ i 1 m ∑ j 1 n A ( i , j ) 2 \text{sum} \sum_{i1}^{m}\sum_{j1}^{n} A(i,j)^2 sumi1∑…...
vue3中 axios 发送请求 刷新token 封装axios
service.js 页面 import axios from axios // 创建axios实例 const instance axios.create({baseURL: http://gcm-test.jhzhkj.cn:8600/h5card/,timeout: 5000, // 请求超时时间headers: {get: {Content-Type: application/x-www-form-urlencoded},post: {Content-Type: appl…...
vue+mars3d叠加展示arcgis动态服务
数据格式:使用arcgis发布的动态服务 叠加和移除arcgis服务图层的方法 //加载arcgis地图服务function arcgisServer(i,d,m,p){i[d.data] new mars3d.layer.ArcGisLayer({name:d.label,url:p,flyTo: true})m.addLayer(i[d.data])}//移除arcgis服务范围线function rem…...
PostgreSQL 中进行数据导入和导出
在数据库管理中,数据的导入和导出是非常常见的操作。特别是在 PostgreSQL 中,提供了多种工具和方法来实现数据的有效管理。无论是备份数据,还是将数据迁移到其他数据库,或是进行数据分析,掌握数据导入和导出的技巧都是…...
Stable Audio Open模型部署教程:用AI打造独家节拍,让声音焕发新活力!
Stable Audio Open 是一个开源的文本到音频模型,允许用户从简单的文本提示中生成长达 47 秒的高质量音频数据。该模型非常适合创建鼓点、乐器即兴演奏、环境声音、拟音录音和其他用于音乐制作和声音设计的音频样本。用户还可以根据他们的自定义音频数据微调模型&…...
python更新程序并部署服务器服务
本地客户端程序 import json import hashlib import os import shutil import requests from pathlib import Pathclass AutoUpdater:def __init__(self, config_path"http://【XXXIP地址】/update_config"):self.config_path config_pathself.config Nonewith op…...
Nmap 扫描技巧:自定义端口、扫描速度与并行化设置
Nmap 扫描技巧:自定义端口、扫描速度与并行化设置 在进行网络安全扫描时,Nmap 是一个非常强大的工具。除了默认扫描 1000 个端口外,你还可以根据需要自定义扫描的端口、调整扫描速度以及优化扫描并行化。今天,我们就来介绍如何通…...
从 HTML 到 CSS:开启网页样式之旅(五)—— CSS盒子模型
从 HTML 到 CSS:开启网页样式之旅(五)—— CSS盒子模型 前言一、盒子模型的组成margin(外边距):border(边框):padding(内边距):conten…...
Linux命令行下载工具
1. curl 1.1. 介绍 curl是一个功能强大的命令行工具,用于在各种网络协议下传输数据。它支持多种协议,包括但不限于 HTTP、HTTPS、FTP、FTPS、SCP、SFTP、SMTP、POP3、IMAP 等,这使得它在网络数据交互场景中有广泛的应用。curl可以模拟浏览器…...
Navicat 连接 SQL Server 详尽指南
Navicat 是一款功能强大的数据库管理工具,它提供了直观的图形界面,使用户能够轻松地管理和操作各种类型的数据库,包括 SQL Server。本文将详尽介绍如何使用 Navicat 连接到 SQL Server 数据库,包括安装设置、连接配置、常见问题排…...
黑马JavaWeb-day06、07、08(SQL部分) _
文章目录 MYSQL概述数据模型SQL简介SQL分类 DDL数据库操作表操作 DML增(INSERT)改(UPDATE)删(DELETE) DQL基本查询条件查询(where)分组查询(group by)排序查询…...
Redis(1)
Redis是一个在内存中存储数据的中间件。 1.在内存中存储数据。 通过数据结构来存储,mysql通过表的方式存储数据,是关系型数据库,redis通过键值对存储,key的类型是string,value的类型是非关系型数据库。 2.可编程的 …...
工具类-列表请求工具 useList
useList 用于列表请求的基于 vue 3 的 hooks,接收请求函数、请求参数等数据,自动生成请求请求函数,分页信息等 本文有涉及到 http 请求工具和接口返回格式的内容: http 工具:一个基于 axios 封装的请求工具Response…...
5G终端自动拔号脚本
5G终端自动拔号脚本 5G终端自动拔号脚本 5G终端自动拔号脚本, 先进入飞行模式,再切出飞行模式, 最后 查询UE IP地址 5G终端自动拔号脚本 input$1 if [ "$input"x "1"x ]; then cmdatcfun1echo "start dialing &…...
3-1 C指针与数组
前言: 基于本人回顾与思考,仅供学习参考 1.0 数组名称的用途 注:可以用于求数组占用的内存空间:sizeof(arrName);此时数组名称代表整个数组 int32 t buffer[5] {1,2,3,4,5};int32 t size sizeof(buffer);printf("sizeof(buffer) %d.\…...
swift 屏幕录制
步骤 1:导入 ReplayKit import ReplayKit步骤 2:开始录屏 let screenRecorder RPScreenRecorder.shared() // 麦克风或系统音频 screenRecorder.isMicrophoneEnabled truefunc startRecording() {guard screenRecorder.isAvailable else {print(&quo…...
Graphviz 的详细介绍
Graphviz 的详细介绍 Graphviz 是一个开源的图形可视化软件,专门用于生成结构化图形。它特别适合用于表示关系图、流程图、依赖关系图和树状结构等类型的图表。Graphviz 使用一种名为 DOT 的脚本语言描述图形,通过解析 DOT 文件生成图像。 Graphviz 的特…...
前端工程化
文章目录 前端工程化模块化与组件化代码规范与风格统一自动化构建与部署性能优化版本控制与团队协作自动化测试 前端工程化 前端工程化是一种将软件工程的方法应用于前端开发的过程,旨在提高开发效率、降低维护成本、优化代码质量,并支持团队协作。以下…...
【LC】41. 缺失的第一个正数
题目描述: 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1: 输入:nums [1,2,0] 输出:3 解释:范围…...
高频面试题(含笔试高频算法整理)基本总结回顾29
干货分享,感谢您的阅读! (暂存篇---后续会删除,完整版和持续更新见高频面试题基本总结回顾(含笔试高频算法整理)) 备注:引用请标注出处,同时存在的问题请在相关博客留言…...
Hive 的 Hook 机制 完全解析
Hive 的 Hook 是一种扩展机制,允许用户在执行查询时自定义行为,例如日志记录、审计或其他操作。Hook 通常在 Hive 的生命周期中某些关键节点被触发,开发者可以插入自定义代码执行特定任务。 一、Hook 的用途和核心概念 1. 用途 审计&#x…...
远程debug
这里写自定义目录标题 一、首先配置idea二、配置jvm1、将刚才idea生成的jvm指令复制下来,就是如下内容(注意要从你的idea中复制)2、在粘贴之前,要拼接上java-jar命令,还有servery,suspendy命令,最后拼接项目…...
一些常见网络安全术语
1、黑帽 为非法目的进行黑客攻击的人,通常是为了经济利益。他们进入安全网络以销毁,赎回,修改或窃取数据,或使网络无法用于授权用户。这个名字来源于这样一个事实:老式的黑白西部电影中的恶棍很容易被电影观众识别&…...
golang学习,小结
切片 切片,底层就是数组,len(切片的长度)和cap(容量,切片的空间) 从一个数组来得到切片,修改切片会修改原来的数组,数据会收到影响 我们可以通过内置的 append 函数对一…...
【C++ map和set】数据的吟游诗:Map与Set的双城记
公主请阅 set1.序列式容器和关联式容器2.set的介绍3.set的构造和迭代器部分set可以进行去重操作的,在去重的同时可以对插入进来的数字进行排序的操作4.set的增删查inserterasefindupper_bound和 lower_bound 5.multiset和set的差异6相关题目349.两个数组的交集142.环…...
leetcode 之 二分查找(java)(3)
文章目录 5. 81. 搜索旋转排序数组 II6. 378、有序矩阵中第k个小的元素 5. 81. 搜索旋转排序数组 II 题目描述: 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。 在传递给函数之前,nums 在预先未知的某个下标 k&#…...
后端返回前端的数据量过大解决方案
后端返回前端的数据量过大解决方案 性能面板(Performance) chrome调试指南 原因 遇到一个页面有好几个表格,部分表格采用虚拟滚动条 数据量有点大 接近快60s了,看一下是哪里导致的慢 后台请求方法执行并不慢 2024-12-04 15:21:52.889 INFO 69948 …...
STL算法之其它算法_下
random_shuffle 这个算法将[first,last)的元素次序随机排列。也就说,在N!中可能的元素排列中随机选出一种,此处N为last-first。 N个元素的序列,其排列方式为N!中,random_shuffle会产生一个均匀分布,因此任何一个排列被…...
MySQL如何区分幻读和不可重复读
在MySQL中,幻读和不可重复读都是并发事务中可能出现的问题,但它们的表现和原因略有不同。 不可重复读 (Non-Repeatable Read) 不可重复读是指在同一个事务内,多次读取同一行数据时,可能会得到不同的结果。这种情况发生在一个事务…...
html ul li 首页渲染多条数据 但只展示八条,其余的数据全部隐藏,通过icon图标 进行展示
<div style"float: left;" id"showMore"> 展开 </div> <div style"float: left;“id"hideLess"> 收起 </div> var data document.querySelectorAll(.allbox .item h3 a); const list document.querySelectorAl…...
Vue3安装 运行教程
本文是综合了所有vue安装教程而成 更细化 更简略 希望对各位读者有所帮助! Vue安装 1. Vue-cli脚手架安装 安装vue的方式有很多 我们这里选择npm方式安装vue npm方式 npm方式安装vue,详细介绍见下文。 1.node.js安装和配置 安装npm 需要安装note.js&…...
Spring事务的一道面试题
每次聊起Spring事务,好像很熟悉,又好像很陌生。本篇通过一道面试题和一些实践,来拆解几个Spring事务的常见坑点。 原理 Spring事务的原理是:通过AOP切面的方式实现的,也就是通过代理模式去实现事务增强。 具体过程是&a…...
PHP SM4 加密
PHP SM4 加密 sm4基类 class Sm4 {private $ck [0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,0xc0c7ced5, 0xdce3ea…...
群控系统服务端开发模式-应用开发-短信工厂腾讯云短信开发
一、腾讯云短信工厂开发 1、添加框架对应的SDK composer require tencentcloud/tencentcloud-sdk-php 2、添加腾讯云工厂 在根目录下extend文件夹下Sms文件夹下channel文件夹下,创建腾讯云短信发送工厂并命名为TencentSmsSender。记住,一定要在腾讯云短…...
vue key属性强制刷新组件
在 Vue 中,key 属性通常用来帮助 Vue 跟踪每个组件或元素的身份,尤其是在使用 v-for 渲染列表时。当 key 值发生变化时,Vue 会销毁并重新渲染组件,这也可以用于强制刷新组件。 如果你想强制刷新一个组件,可以通过动态…...
浪潮X86服务器NF5280、8480、5468、5270使用inter VROC Raid key给NVME磁盘做阵列
浪潮服务器inter VROC Raid key给NVME磁盘做阵列方法 Inter VROC技术简介Raid Key 授权,即VROC SKU兼容性处理器兼容性列表平台和芯片组兼容性列表各Raid级别最大磁盘数量硬盘型号操作系统 服务器上的操作安装Raid Key确认服务器能识别硬盘识别磁盘所在的通道及服务…...
最长最短单词
最长最短单词 C语言实现C实现Java实现Python实现 💐The Begin💐点点关注,收藏不迷路💐 输入1行句子(不多于200个单词,每个单词长度不超过100),只包含字母、空格和逗号。单词由至少一…...
Muduo网络库剖析 --- 架构设计
文章目录 前言概述篇一、Muduo网络库简介Reactor事件处理模式 二、基于muduo实现简易聊天服务器实现测试运行 三、muduo的架构设计Reacor模式muduo框架架构解析主从Reactor工作流程主线程(main Reactor)工作线程(sub Reactor) 线程分配与负载均衡 四、总结线程分配与负载均衡 四…...
lwip raw、netcoon、socket三种接口编程的区别
目录 一、前言 二、LWIP 简介 三、LWIP RAW 编程 1.概念与原理 2.编程模型与流程 3.示例代码 4.优点与缺点 四、LWIP NETCONN 编程 1.概念与原理 2.编程模型与流程 3.示例代码 4.优点与缺点 五、LWIP SOCKET 编程 1.概念与原理 2.编程模型与流程 3.示例代码 …...
在办公室环境中用HMD替代传统显示器的优势
VR头戴式显示器(HMD)是进入虚拟现实环境的一把钥匙,拥有HMD的您将能够在虚拟现实世界中尽情探索未知领域,正如如今的互联网一样,虚拟现实环境能够为您提供现实中无法实现的或不可能实现的事。随着技术的不断进步&#…...
P3916 图的遍历(Tarjan缩点和反向建边)
P3916 图的遍历 - 洛谷 | 计算机科学教育新生态 写法一:Tarjan 思路:先运用Tarjan算法得到每个连通块中最大的编号,然后对每个连通块进行缩点重新建图,进行dfs,得到缩点后的连通块能够达到的最大编号。 Code: conste…...
Element UI 的 el-tree 组件e中默认展开前两层,设置 default-expanded-keys 属性来实现
在使用 Element UI 的 el-tree 组件时,如果你希望默认展开树的前两层节点,可以通过设置 default-expanded-keys 属性来实现。这个属性接受一个数组,数组中的值是需要默认展开的节点的 key。 首先,你需要确保你的每个树节点都有唯…...
Vue 项目中未登录状态如何统一处理
在 Vue 项目中,处理未登录状态(比如用户访问需要登录的页面时)是一项常见的需求。为了实现这一需求,我们通常使用 Vue Router 配合 Vuex 或者 Vue 的全局状态管理来统一处理未登录的状态,确保用户只能访问允许的页面。…...
Java 集合:强大的数据管理工具
在 Java 编程中,集合是一种非常重要的工具,它提供了一种方便的方式来存储和操作一组对象。本文将深入探讨 Java 集合框架,包括其主要类型、特点、用法以及一些最佳实践。 一、引言 在软件开发过程中,我们经常需要处理一组数据。…...
Creating Server TCP listening socket *:6379: bind: No error
启动redis报错:Creating Server TCP listening socket *:6379: bind: No error 解决方案: 1、直接在命令行中输入 redis-cli.exe 2、输入shutdown,关闭 3、输exit,退出 4、重新输入 redis-server.exe redis.windows.conf&…...
iOS免费共享企业证书、苹果最新企业证书免费获取
前言 大家可能都注意到了,苹果手机和安卓手机在安装软件上有点不一样。如果你在苹果手机上想装那些没在官方商店(App Store)里的软件,那就得给它们“签个名”,就像是给它们盖个章,这样手机才能认识它们&am…...
如果用Python写爬虫,具体怎么实现随机请求间隔呢?
在Python中实现随机请求间隔,通常使用time.sleep()函数结合random模块来生成随机的等待时间。以下是一个具体的实现方法: 导入必要的模块 首先,你需要导入time和random模块: import time import random 设置随机间隔 然后&am…...
aws(学习笔记第十五课) 如何从灾难中恢复(recover)
aws(学习笔记第十五课) 如何从灾难中恢复 学习内容: 使用CloudWatch对服务器进行监视与恢复区域(region),可用区(available zone)和子网(subnet)使用自动扩展(AutoScalingGroup) 1. 使用CloudWatch对服务器进行监视与恢复 整体架构 这里模拟Jenkins Se…...
nginx4层限速
Nginx的功能概述 Nginx是一个高性能的HTTP和反向代理服务器,也可以作为邮件代理服务器等。它主要工作在7层(应用层),但在某些场景下也可以实现部分4层(传输层)的功能。 关于4层限速 Nginx自身的限制&#x…...
Spring Cloud Alibaba 之 “Feign多参数构造”
在上一篇文章整合好了Feign,现在来总结以下Feign调用多参数方法的使用。 GET方式: Spring Cloud为Feign支持了Spring Mvc注解的。如果请求的是localhost:8083/test?id1&namecoco,那么如果我们这样写(User实体类有这二个属性)…...