QC 的小树林
311 subscribers
163 photos
17 videos
3 files
578 links
Github: github.com/QuarticCat
Blog: blog.quarticcat.com

分享 / 吐槽 / 存档

欢迎来附属群组聊天
Download Telegram
TIL: cargo tree --duplicates 显示重复依赖
4
发现 perf trace 比 strace 快巨多。已经把 strace -cf 换成 sudo perf trace -s --summary-mode=total
Cursor 配置在同时有普通补全和 AI 补全时,优先触发普通补全:


{
"key": "tab",
"command": "-editor.action.acceptCursorTabSuggestion",
"when": "cpp.shouldAcceptTab"
},
{
"key": "tab",
"command": "editor.action.acceptCursorTabSuggestion",
"when": "cpp.shouldAcceptTab && !(suggestWidgetHasFocusedSuggestion && suggestWidgetVisible && textInputFocus)"
},


原理就是,找到普通补全的 when 条件


{
"key": "tab",
"command": "acceptSelectedSuggestion",
"when": "suggestWidgetHasFocusedSuggestion && suggestWidgetVisible && textInputFocus"
}


取 not 加在 AI 补全的 when 条件后面
1
CSAPP 练习题 5.5 实在太震撼了,直接震撼我的计算机观。我的基础太差了,空中楼阁!🤬回炉重学,统统重学!

题目说,poly 是无脑多项式求和,polyh 是著名的 Horner 求和(嘿 11 年前在大学学过,我强选了一门《数值计算》,现在都记得高斯积分)。

无脑:
static double poly(double a[], double x, long degree) {
long i;
double result = a[0];
double xpwr = x;
for (i = 1; i <= degree; i++) {
result += a[i] * xpwr;
xpwr = x * xpwr;
}
return result;
}

霍纳算法:
static double poly(double a[], double x, long degree) {
long i;
double result = a[degree];
for (i = degree-1; i >= 0; i--)
result = a[i] + x*result;
return result;
}

显然 Horner 求和的时间复杂度常数更低,但是书上说在 Intel Core i7 Haswell 上,Horner 比无脑求和慢 60% (8 vs 5)!

我不信,我在本地的 Intel(R) Core(TM) Ultra 7 155U 上测试,gcc 无优化/-O1/-O2/-O3 均是霍纳慢 35% !

原理大家肯定都懂,毕竟只有我是沙堆起城堡,我就讲点大家可能不知道的,我现在假装不知道两个的源码,手上只有两个 elf,用 perf 来观测两者运行的性能差距体现在哪里。

经过我和 GPT-5 的一番肉搏之后,运行下面的命令(其实跳步骤了,先做 TopdownL1 看到是 tma_core_bound,不重要)
sudo taskset -c 0 perf stat -M tma_ports_utilized_2 -M tma_ports_utilized_3m -M tma_retiring -M tma_core_bound -M tma_memory_bound -e cycles,instructions -- ./polyh

两个 elf 的结果作对比 (poly vs polyh,分析过程可能含有事实错误)
1. IPC: 1.69 vs 0.99 出现端倪
2. tma_ports_utilized_3m: 24.2% vs 6.4% 如果懂 ports utilized 3m 是啥意思的看到这就已经懂了,但我不懂🤬
3. UOPS_EXECUTED.CYCLES_GE_3: 104M vs 49M: better overlap
4. EXE_ACTIVITY.EXE_BOUND_0_PORTS: 22.7M vs 41.7M 说明霍纳有更多的 stall

不行我要做锻炼去了,总之就是震撼,我对计算机的理解不足 1%。
Please open Telegram to view this post
VIEW IN TELEGRAM
Welcome to the Black Parade
CSAPP 练习题 5.5 实在太震撼了,直接震撼我的计算机观。我的基础太差了,空中楼阁!🤬回炉重学,统统重学! 题目说,poly 是无脑多项式求和,polyh 是著名的 Horner 求和(嘿 11 年前在大学学过,我强选了一门《数值计算》,现在都记得高斯积分)。 无脑: static double poly(double a[], double x, long degree) { long i; double result = a[0]; double xpwr = x;…
因为现代 CPU 都是超标量的,有多个功能单元(比如两个算术逻辑单元 + 一个浮点运算单元 + 别的),可以一次性发射多条指令到不同的功能单元一起计算,因此一个 cycle 内实际上可以执行多条指令,称之为 instruction-level parallelism(ILP)。当然高并行的前提是有足够的功能单元以及指令之间没有依赖。有关内容可以阅读一下《现代处理器结构》

我还在用 zen2 没有 TMA 可用。但对于这个场景有非常适合的工具:uiCA 和 llvm-mca。

举个例子,这里的无脑算法我们在 godbolt.org 用 gcc15.2 + O3 编译得到循环体部分的汇编如下:


.L3:
movsd xmm2, QWORD PTR [rax]
add rax, 8
mulsd xmm2, xmm0
mulsd xmm0, xmm3
addsd xmm1, xmm2
cmp rdx, rax
jne .L3


把这串代码丢到 uiCA 模拟,可以得到结果是 4 cycles per iteration。而霍纳算法是 8 cycles per iteration。但是为什么呢?

在 HTML output 里面打开 Trace Table,里面有流水线的可视化模拟,包括指令使用了哪个端口、在第几个周期发射(I)、调度(D)、执行(E)、退役(R)等等。如果调度等了很久,那可能是端口不太够;如果退役等了很久,那可能是指令之间有依赖。在霍纳算法的图里,我们可以看到超长的 E->R 距离,所以降低 IPC 的主因就是指令间依赖了。更多有关 Trace Table 的信息,可以看《Visualizing Performance-Critical Dependency Chains》
6
QC 的小树林
因为现代 CPU 都是超标量的,有多个功能单元(比如两个算术逻辑单元 + 一个浮点运算单元 + 别的),可以一次性发射多条指令到不同的功能单元一起计算,因此一个 cycle 内实际上可以执行多条指令,称之为 instruction-level parallelism(ILP)。当然高并行的前提是有足够的功能单元以及指令之间没有依赖。有关内容可以阅读一下《现代处理器结构》。 我还在用 zen2 没有 TMA 可用。但对于这个场景有非常适合的工具:uiCA 和 llvm-mca。 举个例子,这里的无脑算法我们在…
llvm-mca 也可以试试,它和 uiCA 的模拟结果有一些区别。 goldbolt.org 已经把它集成进去了,使用的时候记得加上 -mcpu=xxx 参数指定 CPU(默认 native 而 goldbolt.org 有多台不同配置的机器)和 -timeline 参数打开流水线可视化。

要注意的是,这类工具无法模拟访存延迟(不知道会在哪一级缓存)和分支(不知道是否跳转)。当需要考虑这些因素的时候,还是得实际运行并且使用 perf 进行分析。

对于 ILP 优化感兴趣的,也可以看一看 algorithmica 里面的第三章节。还有一个我觉得不错的案例:ska sort,一种优化过后的 in-place radix sort。
👍32
鼠标时不时卡住动不了一会,但是按键都能正常工作。debug 半天发现是传感器进猫毛了🤦
🥰5
鉴于当前各大 LLM 逐步普及​​以零宽字符为代表的文本隐写水印手段,为此我特地写了一个小工具,专门用于扫描文本中的隐蔽​​​/不可​见 Unicode 码点,便于​​​​快速​定位​可能存在的ㅤ「文本水印」。

目前​可检测​​​的特殊 Unicode 码点与类别如下 (包括但不限于):

- ZWSP: 零宽空格
- ZWNJ: 零宽非连字
- ZWJ: 零宽连字
- BOM: 字节序标记
- WJ: 单词连接符
- MVS: 蒙古元音​分隔符
- SHY: 软连字符
- 特殊标点混用,例如: 

连字符混用: - (U+002D) vs. − (U+2212) vs. – (U+2013)
撇号混用: ' (U+0027) vs. ’ (U+2019)
句点混用: . (U+002E) vs. . (U+0323)


除字符​​扫描外​​​,​还支持​​基于 cl100k_base (GPT-4) ​& o200k_base (GPT-4o) BPE Tokenization 进行分词,便于辅助判定

快速体验​: https://links.xmsl.dev/analyzer 欢迎​​反馈

示例文本 (内含​​隐写​​水印):
(本文​遍布​零宽字符​,直接​右键复制​本文​即可查看)


* 更新: LLM 文本​​水印实​​现原理和​​解释请参考 https://t.iss.one/hatschannel/1127
1