前两天用 AI 帮我做数据分析,有一些数据要算 RMSE 和相关系数。数据很多,都丢给 AI 去弄了,结果在没意料的地方出了错——它偷懒了,我没发现,hhh。
事情是这样的:两个方向量做比较的时候,误差是不应该大于 180° 的。这个道理我是知道的,但当时没交代清楚。比如 355° 和 5°,它们相差不是 abs (355-5)=350°,而是:如果差值大于 180,就用 360 减去差值,也就是 360-350=10°。差值是 10°,这样最后算出来的 RMSE 才是对的。
我和 AI 说了之后,它批量去弄了。出来的图片看起来好像是那么回事,RMSE 显示 60 多度。我心想行吧,就这样了。结果后来客户说:"你这个和我之前算的不一样啊,你再检查检查?" 再去一查,hhh,尴尬了——AI 画图的时候用了正确的方法,但计算 RMSE 还是原来那套逻辑。
怎么说了?可以说我一开始没说清楚,或者是模型能力问题,它偷懒了——但这种事用 skill 其实是可以解决的:把一些常用的方法和套路固定下来,让 AI 有参考,或者直接调用。
东西做完了之后回头再看,最后的东西其实不只是一个能用的脚本,也是一套可以复用的 "坑 → 规则 → 加固" 模式。写下来也算是个记录,或许对正在做类似事情的人有些参考。
1. AI 画对了不代表算对了。 这是有坑的一点。AI 在出图时用了正确的方向差值方法(因为图的形状看起来合理),但在表格里计算 RMSE 时用的还是普通减法。明明调用了同一份数据,两个地方的结果不一致——这种"半对半错"比全错更隐蔽。后来把所有指标计算统一到一个核心模块 metrics.py 里,图和报告都调用同一个函数,也就应该解决了这个问题。
2. 让它"不敢犯错"比告诉它"别犯错"靠谱。 一开始在 skill 里写了很多"注意:方向数据要用循环差值"之类的提示。但实验发现,AI 看到提示后仍然有可能忽略。后来改了策略:不用自然语言提醒,把规则直接写进代码里—— direction_rmse 函数内部强制调用 circular_diff,外部想绕绕不过去。
3. 加上人工检查点。 Skill 做得再好,也不能 100% 覆盖所有场景。所以在每个阶段(提取 → 对齐 → 计算 → 画图)都设置了一个人工检查点,输出显式的日志(对齐了多少点、剔除了多少 NaN、误差过滤了多少个),可以看到有没有异常。这不是对 AI 不信任,主要是检查下放心点可能。
这个 skill 的过程中,把常见的 AI 失误整理成了一个"反例章节",每个反例都按三段式来写:
❌ 错误写法 → 展示 AI 会怎么犯错 ✅ 正确做法 → 给出应该怎么做 代码加固 → 说明代码层面如何防止
比如:
merge_asof 模糊对齐,允许几分钟的窗口感觉 skill 能稳定交付的本质原因不是某个脚本写得多好,还是要有一些约束:
| 层级 | 做什么 | 例子 |
|---|---|---|
| 文档层 | 告诉 AI "这里有坑" | 反例章节 + 各阶段的规范指南 |
| 代码层 | 让 AI 想踩坑也踩不了 | circular_diff 强制调用、列名类型推断、NaN 显式报告 |
| 流程层 | 让结果多一道肉眼把关 | 人工检查点、自检清单、详细的日志输出 |
这三层还是比较重要。没有文档层,AI 不知道方向数据要特殊处理;没有代码层,它知道了也可能忘;没有流程层,错了也没人发现。
以后遇到类似的重复性工作,可以想一下:能不能做成一个 skill?不一定每次都能,但思路摆在这里。这是 skill 链接: https://github.com/yangsir60/data-skill
]]>界面是这个样子的:
卡片视图比列表视图慢一点,双击某一条,就会放到剪贴板,然后直接粘贴到当前的光标处。
右上角的加号就是添加自己需要的条目,选中条目可以,编辑、删除。在编辑视图可以移动到不同分类。
平时是用快捷键呼出,默认是 ctrl+shift+x 的,也可以更改,在软件目录的 config 下面,ai 用python 写的还是很方便;
arch+win双系统安装视频教程 ,也是一个 b 站 up 的视频比较长,但详细

lsblk 命令查看自己剩余的磁盘空间是哪个,就用这个来做 archlinux 系统的磁盘
cfdisk /dev/(你需要的硬盘如:sda,或者其他的) 工具做一下简单分区,上面讲双系统的哪个教程非常详细archinstall 进行脚本快速安装,注意一般国内网络这个时候还有问题,在 archinstall 之前,首先 sudo reflector --country China --latest 10 --sort rate --save /etc/pacman.d/mirrorlist, 运行大概要个 1 min 左右吧可能也不需要,成功后会有提示,就是修改 mirrorlist 里面内容为中国镜像,然后 archinstall 安装就快了(然后可以选择看看《前置说明的教程 3 或 5》)



vim ~/.config/kitty/kitty.conf用 niri 畅享丝滑, ok
FlashBrowser \_x64_v1.1.6 项目 ,一个直接支持 flash 的浏览器,登录网站就能直接玩很方便
Flash. Collector 1.13.0_win-x 64 项目,一个支持下载 flash 软件,输入网站把 flash 下载下来玩,但是有些 flash 下载不全;
本文档详细介绍了在Windows环境下配置和使用Bandicoot-CUDA进行GPU加速计算的完整流程。Bandicoot是一个基于CUDA的C++线性代数库,能够显著提升矩阵运算性能。
请访问以下官方网站查询您的显卡是否支持CUDA:
历史版本显卡支持
下面文章中配置写的 sm 61 ,也是在这两个网页里面查看
步骤1:卸载旧版本
如果系统中已安装CUDA,建议先完全卸载后重新安装,确保环境干净。
步骤2:下载安装CUDA
参考资料: CUDA环境配置详细教程
步骤1:创建测试项目
步骤2:处理兼容性问题
如果遇到显卡计算能力不足的错误,需要:

注意对于非 cuda 项目,例如纯 qt 项目,属性里面没有 cuda c/C++,可以如下图进行配置:
步骤3:验证安装成功
测试代码能够正常编译并运行,说明CUDA环境配置成功,注意测试代码可以在 main 最下面加上 std::cin.get() 暂停看下结果。
如需在非 CUDA 项目中使用 CUDA 功能,请参考:Visual Studio中CUDA配置方法
下载Bandicoot源码
下载OpenBLAS库
步骤1:CMake-GUI配置

打开CMake-GUI后进行以下配置:
步骤2:处理配置错误

配置过程中会出现红色错误提示,这是正常现象:

按照提示逐项修改配置参数:

步骤3:生成项目文件
配置完成后,点击"Generate"生成Visual Studio解决方案文件。
.sln文件
重要提示: 请创建新的项目,不要在CUDA Runtime测试项目中添加Bandicoot,避免CUDA代码冲突。
右键项目 → 属性,进行以下配置:
包含目录配置
库目录配置
预处理器定义

在"附加依赖项"中添加以下库文件:
bandicoot.lib
libopenblas.lib
cublas.lib
cublasLt.lib
cuda.lib
cudadevrt.lib
cudart.lib
cudart_static.lib
curand.lib
cusolver.lib
nvrtc.lib注意: OpenBLAS库路径需要根据实际安装位置调整,例如:
E:\vsproject\bandicoot-2.1.1\OpenBLAS\lib\libopenblas.lib参考资料: 完整的CUDA库配置列表(并不需要这么完整的)
创建Qt Console项目后,在代码开头添加必要的配置:
// 禁用OpenCL支持(必须)
#define COOT_DONT_USE_OPENCL 1
// 数学常量定义(必须)
#define _USE_MATH_DEFINES
#include <math.h>
#include <cmath>
// Bandicoot库
#include <bandicoot>
using namespace coot;重要说明:
#define COOT_DONT_USE_OPENCL 1 必须添加,否则会与CUDA产生冲突常见编译错误修复:
在alias_wrapper.hpp文件第66行附近,找到以下代码:
template<typename T2>
constexpr //static // 注释掉这个static关键字
coot_inline
typename enable_if2< !is_Mat<T2>::value && !is_subview<T2>::value && !is_diagview<T2>::value && !is_Cube<T2>::value && !is_subview_cube<T2>::value, bool >::result
check(const T2&)将static关键字注释掉即可解决C++语法兼容性问题。
以下是集成了Armadillo(CPU)和Bandicoot(GPU)的性能对比测试代码:
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
# pragma execution_character_set("utf-8")
#endif
#include <QtCore/QCoreApplication>
#include <qdebug.h>
#include <QElapsedTimer>
// 必要的数学库定义
#define _USE_MATH_DEFINES
#include <math.h>
#include <cmath>
// Bandicoot GPU库配置
#define COOT_DONT_USE_OPENCL 1
#include <bandicoot>
#define COOT_KERNEL_CACHE_DIR "D:\\cuda_cache_can_delete" //这个可能没效果
using namespace coot;
// Armadillo CPU库
#include <armadillo>
using namespace arma;
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
qDebug() << "GPU加速计算性能测试程序启动...\n";
// 矩阵维度配置
const int rows = 10000;
const int cols = 10000;
// ======================== CPU计算流程(Armadillo) ========================
qDebug() << "=== CPU计算(Armadillo库) ===";
QElapsedTimer cpu_create_timer, cpu_calc_timer, cpu_total_timer;
// CPU矩阵创建阶段
cpu_total_timer.start();
cpu_create_timer.start();
arma::mat cpu_A(rows, cols, arma::fill::randu);
arma::mat cpu_B(rows, cols, arma::fill::randu);
qint64 cpu_create_elapsed = cpu_create_timer.elapsed();
qDebug() << "CPU创建矩阵耗时:" << cpu_create_elapsed << "毫秒";
// CPU计算阶段
cpu_calc_timer.start();
arma::mat cpu_C = cpu_A * cpu_B;
qint64 cpu_calc_elapsed = cpu_calc_timer.elapsed();
qint64 cpu_total_elapsed = cpu_total_timer.elapsed();
qDebug() << "CPU矩阵乘法计算耗时:" << cpu_calc_elapsed << "毫秒";
qDebug() << "CPU总流程耗时:" << cpu_total_elapsed << "毫秒";
// 显示CPU计算结果样本
qDebug() << "CPU计算结果(第一行前11列):";
cpu_C.row(0).cols(0, 10).print();
// ======================== GPU计算流程(Bandicoot) ========================
qDebug() << "\n=== GPU计算(Bandicoot库) ===";
QElapsedTimer gpu_create_timer, gpu_calc_timer, gpu_total_timer;
// GPU矩阵创建阶段
gpu_total_timer.start();
gpu_create_timer.start();
coot::fmat gpu_X1(rows, cols, coot::fill::randu);
coot::fmat gpu_X2(rows, cols, coot::fill::randu);
qint64 gpu_create_elapsed = gpu_create_timer.elapsed();
qDebug() << "GPU创建矩阵耗时:" << gpu_create_elapsed << "毫秒";
// GPU计算阶段
gpu_calc_timer.start();
coot::fmat gpu_X3 = gpu_X1 * gpu_X2;
qint64 gpu_calc_elapsed = gpu_calc_timer.elapsed();
qint64 gpu_total_elapsed = gpu_total_timer.elapsed();
qDebug() << "GPU矩阵乘法计算耗时:" << gpu_calc_elapsed << "毫秒";
qDebug() << "GPU总流程耗时:" << gpu_total_elapsed << "毫秒";
// ======================== 性能对比分析 ========================
qDebug() << "\n=== 性能对比分析 ===";
qDebug() << "测试矩阵规模:" << rows << "×" << cols << " × " << rows << "×" << cols;
qDebug() << "----------------------------------------";
qDebug() << "| 计算阶段 | CPU耗时(ms) | GPU耗时(ms) | 加速比 |";
qDebug() << "----------------------------------------";
double create_speedup = gpu_create_elapsed > 0 ?
(double)cpu_create_elapsed / gpu_create_elapsed : 0.0;
double calc_speedup = gpu_calc_elapsed > 0 ?
(double)cpu_calc_elapsed / gpu_calc_elapsed : 0.0;
double total_speedup = gpu_total_elapsed > 0 ?
(double)cpu_total_elapsed / gpu_total_elapsed : 0.0;
qDebug() << QString("| 矩阵创建 | %1 | %2 | %3x |")
.arg(cpu_create_elapsed, 8)
.arg(gpu_create_elapsed, 8)
.arg(create_speedup, 0, 'f', 2);
qDebug() << QString("| 矩阵乘法 | %1 | %2 | %3x |")
.arg(cpu_calc_elapsed, 8)
.arg(gpu_calc_elapsed, 8)
.arg(calc_speedup, 0, 'f', 2);
qDebug() << QString("| 总体流程 | %1 | %2 | %3x |")
.arg(cpu_total_elapsed, 8)
.arg(gpu_total_elapsed, 8)
.arg(total_speedup, 0, 'f', 2);
qDebug() << "----------------------------------------";
if (calc_speedup > 1.0) {
qDebug() << QString("GPU在矩阵乘法计算中实现了 %1 倍加速!").arg(calc_speedup, 0, 'f', 2);
} else {
qDebug() << "注意:当前测试中GPU性能未超过CPU,可能原因:";
qDebug() << "1. 矩阵规模较小,GPU并行优势未充分体现";
qDebug() << "2. GPU初始化开销较大";
qDebug() << "3. 建议增大矩阵规模进行测试";
}
return app.exec();
}关键配置项:
COOT_DONT_USE_OPENCL 1:禁用OpenCL,避免与CUDA冲突_USE_MATH_DEFINES:启用数学常量定义COOT_KERNEL_CACHE_DIR:设置CUDA内核缓存目录(可选)性能测试功能:
问题: alias_wrapper.hpp中的static关键字编译错误
解决方案: 在该文件第66行附近注释掉static关键字
问题: 缺少数学常量定义
解决方案: 确保在代码开头添加:
#define _USE_MATH_DEFINES
#include <math.h>
#include <cmath>问题: 找不到CUDA库文件
解决方案:
.lib文件是否存在问题: OpenBLAS库路径错误
解决方案: 根据实际安装位置调整库文件路径
问题: 显卡计算能力不足
解决方案:
问题: GPU性能未达到预期
解决方案:
问题: CMake配置失败
解决方案:
问题: DLL文件缺失
解决方案:
本文档提供了在Windows环境下配置Bandicoot-CUDA GPU加速计算的完整指南。通过正确配置CUDA环境、编译Bandicoot库并在Visual Studio中进行项目配置,可以实现显著的矩阵运算性能提升。
关键要点:
遵循本指南的步骤,您应该能够成功在 windows 下配置并使用Bandicoot进行高性能的GPU加速计算。
]]>
之前电脑中病毒,下载了 360 杀毒 pro,昨天逛知乎才知道 360 居然有时候读写磁盘次数非常多,把 360 关了,用知友说的软件看了下,没想到 edge 才是隐藏 boss,打开软件,读写都干冒烟, 下面是一些原帖子:
怎么看2025年360安全卫士写入事件致使用户固态硬盘提前报废?
用的 AppReadWriteCounter 软件
吾爱破解上的AppReadWriteCounter
还写了个脚本:
@echo off
taskkill /f /im msedge.exe >nul 2>&1
taskkill /f /im msedgewebview2.exe >nul 2>&1
echo 操作完成,按任意键退出... & pause >nul
]]>就是桌面上应用软件会自动给你排好,排整齐无堆叠,现在 arch 下面的 niri 还是好用. 主要是处理多任务的时候直观方便。下面是 windows 桌面的截图
这两天又折腾了下 windows 下的平铺软件【安装了komorebi和yasb】,之前就弄过 FancyWM, 比较方便简单,开箱即用,但是有时候感觉暂时有点卡卡的。主流的好像也就是三个。
komorebi 怎么说了,最开始也不会用,🤣可能这才是常态。去 github 上下载了最新的程序,结果安装桌面连个快捷方式也没有,还好会用 everything 搜索,里面一堆程序
最开始点了那个 1 的 exe,弹一个黑框框,就让他一直显示也能用,就是有点丑还不是后台的运行,后来看了使用介绍才知道,可以用那个 2,在 cmd 里面运行 komorebic.exe start 就静默运行了,然后 komorebic.exe -h 里面实际上是有很多介绍,一些命令快捷操作,弄了还是很方便
2 个经验:
其实 yasb 和 komorebi 安装还是简单,主要是使用

去 github 上下载了(cer 和 msixbundle 文件),用 PowerShell (as Administrator) 就可以安装
certutil.exe -addstore TrustedPeople .\FancyWM.Package_1.0.0.0.x64.cer
Add-AppxPackage -Path .\FancyWM.Package_1.0.0.0.x64.msixbundle人类寿命的上限是一个长期存在的研究课题。现代科学研究与古代文献记载在这一问题上呈现出某种一致性。
目前存在两个主要的科学理论。
海夫利克极限理论(Hayflick Limit)指出,由美国生物学家 伦纳德・海夫利克(Leonard Hayflick 于 1961 年提出,人体细胞的分裂次数有限,约为 40-60次。每次分裂时,染色体末端的端粒会缩短。当端粒缩短至临界值时,细胞停止分裂,机体进入衰老状态。根据此理论计算,人类寿命上限约为120岁。海夫利克极限是细胞生物学领域的核心理论1
生理韧性理论是近年来提出的新观点。发表在《自然通讯》上的研究表明,人体的自我修复能力随年龄增长而下降。研究模型显示,在120至150岁之间,人体的修复能力将降至临界点,此时即使无重大疾病,生命也难以维持。
这两个理论从不同角度将人类寿命极限定位在120-150岁区间。
中国古代典籍中也有相关论述。
古代文献的记载与现代科学研究结论存在相似性。这些记载基于长期的生活观察和经验总结。
从现有证据来看,人类寿命存在一定的生物学上限。科学研究与历史文献都指向相似的数值范围。
对个体而言,在既定的生命长度内如何维持健康状态,可能比追求极限寿命更具现实意义。
参考资料:
六月【6-27】的时候去一个【卷桥河公园】非常大,就是天气太热了,还租了个车没跑一会然后就没起了,最后还是走回来的,下面是照片
太阳很好,颜色很正。



这张忘记在哪拍的了【7 月 2 日拍的】
去了一个动物园,野生动物园,还看见了大棕熊和老虎






【去江边公园拍到的】

今天拍的小猫
大致思路是:
下面在这个网盘下面提供 2 个 PDF 和一个代码方便之后回顾学习
https://a.siyouyun.ren:30597/OutSaveFile2/RadarXG/ESPRIT_Double_mimo
clc,clear all,close all;
%% Parameters of the radar system
M = 7; % number of Tx
N = 7; % number of Rx
d = 0.5; % inter-element space
% theta = [15 -10 5]; % DOA
% phi = [20 35 60];
theta = [-50 20 60]; % DOD % DOA
phi = [20 40 60];
K = length(theta); % number of target % dopplor frequency shift
L = 100; % number of sanpshot
SNR = 30; % signal-to-noise ratio before matched filtering
Geo_Rx = [0:N-1]; % geometry of Rx
Geo_Tx = [0:M-1]; % geometry of Tx
At = exp(-j*2*pi*d*Geo_Tx.'*sind(phi)); % transmitting direction matrix
Ar = exp(-j*2*pi*d*Geo_Rx.'*sind(theta)); % receiving direction matrix
item = 10;
%% 设置互耦系数;
mc_K = 2;
mc_nb = mc_K+1;
C_t = generateMCMmat(M,mc_nb);
C_r = generateMCMmat(N,mc_nb);
C = kron(C_t,C_r);
%% 设置选择Pt和Pt矩阵
Pt = [zeros(M-2*mc_K,mc_K),eye(M-2*mc_K),zeros(M-2*mc_K,mc_K)];
Pr = [zeros(N-2*mc_K,mc_K),eye(N-2*mc_K),zeros(N-2*mc_K,mc_K)];
M1 = M-2*mc_K;
N1 = N-2*mc_K;
P = kron(Pr,Pt);
% number of trials
%% Selective matrices
JM1 = [eye(M1-1),zeros(M1-1,1)];
JM2 = [zeros(M1-1,1),eye(M1-1)];
JN1 = [eye(N1-1),zeros(N1-1,1)];
JN2 = [zeros(N1-1,1),eye(N1-1)];
Jt1 = kron(JM1,eye(N1));
Jt2 = kron(JM2,eye(N1));
Jr1 = kron(eye(M1),JN1);
Jr2 = kron(eye(M1),JN2);
a_kronrao = zeros(M*N,K);
for i=1:K
a_kronrao(:,i) = kron(At(:,i),Ar(:,i));
end
for item_num = 1:item
disp(['SNR = ',num2str(SNR),' dB, ',num2str(item_num), ' # try : ']);
%% Matched Filtering
S = randn(K,L)+1i*randn(K,L);
X_0 = C*a_kronrao * S;
X = awgn(X_0,SNR,"measured","dB");
Y = P * X;
%% Eigen decomposition
%Rx = (X*X')/L; % Estimated covariance matrix
Rx = (Y*Y')/L;
[Es,D] = eigs(Rx,K,'LM'); % Signal subspace
%% Rotational invariant property
Vt = pinv(Jt2*Es)*Jt1*Es;
%Vt = pinv(Jt1*Es)*Jt2*Es;
[T,Phit] = eig(Vt);
Phir = inv(T)*pinv(Jr2*Es)*Jr1*Es*T;
%Phir = inv(T)*pinv(Jr1*Es)*Jr2*Es*T;
E_theta = asind(angle(diag(Phir))/pi).';
E_phi = asind(angle(diag(Phit))/pi).';
plot(E_theta,E_phi,'k*');hold on;
end
H(1)=plot(E_theta,E_phi,'k*');hold on;
H(2)=plot(theta,phi,'rx','markersize',28);grid on;
xlabel('DOA'),ylabel('DOD');
legend([H(1),H(2)],'Esimated','Ture')没想到 matlab 还可以画出这样的图片,“赛博生命”,hhh
https://mp.weixin.qq.com/s/GS-jSHnasVxrrIn5C2E3WQ
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl = scatter([], [], 2, 'filled','o','w', 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.4);
t = 0;
i = 0:2e4;
x = mod(i, 100);
y = floor(i./100);
k = x./4 - 12.5;
e = y./9 + 5;
o = vecnorm([k; e])./9;
while true
t = t + pi/90;
q = x + 99 + tan(1./k) + o.*k.*(cos(e.*9)./4 + cos(y./2)).*sin(o.*4 - t);
c = o.*e./30 - t./8;
SHdl.XData = (q.*0.7.*sin(c)) + 9.*cos(y./19 + t) + 200;
SHdl.YData = 200 + (q./2.*cos(c));
drawnow
end
]]>