AMD Zen 3 與 Zen 4 上 FSRM (Fast Short REP MOV) 的效能問題

前幾天 Hacker News 上討論到的一篇:「Rust std fs slower than Python? No, it's hardware (xuanwo.io)」,原文則是在「Rust std fs slower than Python!? No, it's hardware!」。

原因是作者收到回報,提到一段 Rust 寫的 code (在文章裡面的 read_file_with_opendal(),透過 OpenDAL 去讀) 比 Python 的 code 還慢 (在文章裡面的 read_file_with_normal(),直接用 Python 的 open() 開然後讀取)。

先講最後發現問題是 Zen 3 (桌機版 5 系列的 CPU) 與 Zen 4 (桌機版 7 系列的 CPU) 這兩個架構上 REP MOV 系列的指令在某些情境下 (與 offset 有關) 有效能上的問題。

FSRM 類的指令被用在 memcpy()memmove() 類的地方,算是很常見備用到的功能,這次追蹤的問題發現在 glibc 裡面用到導致效能異常。

另外也可以查到在 Linux kernel 裡面也有用到:「Linux 5.6 To Make Use Of Intel Ice Lake's Fast Short REP MOV For Faster memmove()」,所以後續應該也會有些改善的討論...

Ubuntu 這邊的 issue ticket 開在「Terrible memcpy performance on Zen 3 when using rep movsb」這,上游的 glibc 也有對應的追蹤:「30995 – Zen 4: sub-optimal memcpy on very large copies」。

從作者私下得知的消息,因為 patch space 的大小限制,AMD 可能無法提供 CPU microcode 上的 patch,直接解決問題:

However, unverified sources suggest that a fix via amd-ucode is unlikely (at least for Zen 3) due to limited patch space. If you have more information on this matter, please reach out to me.

所以目前比較可行的作法是在 glibc 裡面使用到 FSRM 的地方針對 Zen 3 與 Zen 4 放 workaround,回到原來沒有 FSRM 的方式處理:

Our only hope is to address this issue in glibc by disabling FSRM as necessary. Progress has been made on the glibc front: x86: Improve ERMS usage on Zen3. Stay tuned for updates.

另外在追蹤問題的過程遇到不同的情境,得拿出不同的 profiling 工具出來用,所以也還蠻值得看過一次有個印象:

一開始的 timeit 算是 Python 裡面簡單的 benchmark library:

接著的比較是用 command line 的工具 hyperfine 產生出來的 (給兩個 command 讓他跑),查了一下發現在 Ubuntu 官方的 apt repository 裡面有包進去 (22.04+):

再來是用 strace 追問題,這個算是經典工具了,可以拿來看 syscall 被呼叫的時間點:

到後面出現了 perf 可以拿來看更底層的資訊,像是 CPU 內 cache 的情況:

接續提到的「hotspot ASM」應該也還是 perf 輸出的格式,不過不是那麼確定... 在「perf Examples」這邊可以看到 function 的分析:

而文章裡的則是可以看到已經到 assembly 層級了:

差不多就這些...

在 Cleanfeed 裡面用 Mail::SpamAssassin 的 Bayesian filter 來擋 Google Groups 的垃圾

本來單純用 Cleanfeed + Mail::SpamAssassin 擋,效果其實不太好:「Google Groups 的巨量 spam」。

後來在 news.software.nntp 討論區裡面有人提到應該要用 sa-learn 訓練:

OK, now you need a ~/.spamassassin directory for your news user and a user_prefs file in that directory. After that you can start adding rules for Usenet spam. You will also need to feed several hundreds of spam and ham articles to sa-learn --spam or sa-learn --ham as the news user. After that, SpamAssassin will gradually improve.

死馬當活馬醫看看,結果看起來效果就出來了:

累積了幾天下來後,單看跑進 comp.lang.c 裡面的 spam 與 Mail::SpamAssassin 這邊擋下來的量,差不多是 99%+ 的量,接下來就是有看到的部分再丟進去 train。

目前看起來唯一的問題就是 Google Groups 的 spam 量真的很大,導致 innd 因為跑 Mail::SpamAssassin 的 bayesian 運算時 CPU usage 會高不少,偶而會撞到 100%,但不是常態所以還好。

繼續觀察看看...

Mac (M1/M2) 上的 Asahi Linux 支援 OpenGL ES 3.1

在「The first conformant M1 GPU driver」這邊看到 Mac (M1 系列與 M2 系列) 上的 Asahi Linux 支援 OpenGL ES 3.1 了。

文章裡面有提到,目前 macOS 上沒有業界標準介面可以用:

Unlike ours, the manufacturer’s M1 drivers are unfortunately not conformant for any standard graphics API, whether Vulkan or OpenGL or OpenGL ES. That means that there is no guarantee that applications using the standards will work on your M1/M2 (if you’re not running Linux).

也許有機會會看到有人 backport 回 macOS 上?

strlcpy() 與 strlcat() 被加入 glibc

Hacker News 上看到「Strlcpy and strlcat added to glibc 2.38 (sourceware.org)」這個,印象中極度排斥 strlcpystrlcatglibc 要包進去了。

主要的原因在原始的 commit log 裡面有提到,是因為 POSIX 標準要放入這兩個 function 了:

These functions are about to be added to POSIX, under Austin Group issue 986.

找了一下提到的 Austin Group issue 986,最後更新是 2022 年,看起來進度不快,但是就是一直推進?

反過來看了一下 Hacker News 上的討論,果然有人把當年 Ulrich Drepper 臭 BSD 流派的信件翻出來:「Re: PATCH: safe string copy and concetation」。

Python 內建的工具

Hacker News Daily 上看到「CLI tools hidden in the Python standard library」這個,在講 Python 內建的工具。

其中 python -m calendar 這組看起來還不錯,測了一下可以用 python -m calendar 2024 顯示所有 2024 的月曆,用 python -m calendar 2024 1 則可以顯示 2024 一月單月的月曆。

這操作起來比先前用的 ncal 好多了,先前用 cal 2024 會出現錯誤,因為只有一個參數時他會當作月份,而兩個參數時要把月份放前面,也就是用 cal 1 2024 才能正確顯示。

所以就把本來的 ncal 移除掉,改用 alias 來處理:「Add alias "cal".」。

其他的大多都有習慣的工具了,像是 base64 可以用 openssl base64 處理;而 json.tool 有 jq 可以用。

在 Intel 內顯上面直接跑 CUDA 程式的 ZLUDA

Hacker News 首頁上看到的有趣東西:「Zluda: Run CUDA code on Intel GPUs, unmodified (github.com/vosen)」,專案在「CUDA on Intel GPUs」這邊,這是個最後更新在 2021 年的專案。

這個專案的想法可以猜得出來,想要吃 CUDA 的 ecosystem,把現有用 CUDA 的應用程式直接跑在 Intel 的 GPU 上面,這樣對於一些只有 CUDA 卻沒有 OpenCL 的實作就有機會拿來用。

一開始本來以為是給 Intel 新的獨立顯卡 Arc,結果發現是 2021 年就停更的專案,是以內顯來測試的:

ZLUDA performance has been measured with GeekBench 5.2.3 on Intel UHD 630.

從 benchmark 的結果看起來,大多數的功能應該都有 porting 上去,所以至少測試是能跑的,而不是 crash:

不過 Hacker News 的討論上可以看到似乎還是有問題,而且大多數的 AI 應用還是會回頭支援 OpenCL,似乎沒有那麼好用...

macOS 要提供 DirectX 介面了

Hacker News 上看到 macOS 要提供 DirectX 介面了:「DirectX 12 Support on macOS (twitter.com/andytizer)」,原推是:

算是降低遊戲引擎維護的成本?讓開發商更有意願實作?不確定會有什麼效果...

Georgi Gerganov 成立公司 GGML

Hacker News 首頁上看到 Georgi Gerganov 成立公司的計畫:「GGML – AI at the Edge (ggml.ai)」,官網在「GGML - AI at the edge」。

如同 Georgi Gerganov 提到的,llama.cpp 這些專案本來是他的 side project,結果意外的紅起來:

另外他提到了 Nat FriedmanDaniel Gross 也幫了一把:

在官網則是有提到是 pre-seed funding:

ggml.ai is a company founded by Georgi Gerganov to support the development of ggml. Nat Friedman and Daniel Gross provided the pre-seed funding.

現在回頭來看,當初 llama.cpp 會紅起來主要是因為 CPU 可以跑 LLaMA 7B,而且用 CPU 跑起來其實也不算慢。

後來吸引了很多人一起幫忙,於是有了不少 optimization (像是「llama.cpp 的載入速度加速」這邊用 mmap 減少需要載入的時間,並且讓多個 process 之間可以重複使用 cache),接下來又有 GPU 的支援...

但不確定他開公司後,長遠的計畫是什麼...?

把 RabbitMQ 換成 PostgreSQL 的那篇文章...

Hacker News 上看到「SQL Maxis: Why We Ditched RabbitMQ and Replaced It with a Postgres Queue (prequel.co)」這篇文章,原文在「SQL Maxis: Why We Ditched RabbitMQ And Replaced It With A Postgres Queue」這邊,裡面在講他們把 RabbitMQ 換成 PostgreSQL 的前因後果。

文章裡面可以吐嘈的點其實蠻多的,而且在 Hacker News 上也有被點出來,像是有人就有提到他們遇到了 bug (或是 feature) 卻不解決 bug,而是決定直接改寫成用 PostgreSQL 來解決,其實很怪:

In summary -- their RabbitMQ consumer library and config is broken in that their consumers are fetching additional messages when they shouldn't. I've never seen this in years of dealing with RabbitMQ. This caused a cascading failure in that consumers were unable to grab messages, rightfully, when only one of the messages was manually ack'ed. Fixing this one fetch issue with their consumer would have fixed the entire problem. Switching to pg probably caused them to rewrite their message fetching code, which probably fixed the underlying issue.

另外一個吐嘈的點是量的部份,如果就這樣的量,用 PostgreSQL 降低使用的 tech stack 應該是個不錯的決定 (但另外一個問題就是,當初為什麼要導入 RabbitMQ...):

>To make all of this run smoothly, we enqueue and dequeue thousands of jobs every day.

If you your needs aren't that expensive, and you don't anticipate growing a ton, then it's probably a smart technical decision to minimize your operational stack. Assuming 10k/jobs a day, thats roughly 7 jobs per minute. Even the most unoptimized database should be able to handle this.

在同一個 thread 下面也有人提到這個量真的很小,甚至直接不講武德提到可以用 Jenkins 解 XD:

Years of being bullshitted have taught me to instantly distrust anyone who is telling me about how many things they do per day. Jobs or customers per day is something to tell you banker, or investors. For tech people it’s per second, per minute, maybe per hour, or self aggrandizement.

A million requests a day sounds really impressive, but it’s 12req/s which is not a lot. I had a project that needed 100 req/s ages ago. That was considered a reasonably complex problem but not world class, and only because C10k was an open problem. Now you could do that with a single 8xlarge. You don’t even need a cluster.

10k tasks a day is 7 per minute. You could do that with Jenkins.

然後意外看到 Simon Willison 提到了一個重點,就是 RabbitMQ 到現在還是不支援 ACID 等級的 job queuing (尤其是 Durability 的部份),也就是希望 MQ 系統回報成功收到的 task 一定會被處理:

The best thing about using PostgreSQL for a queue is that you can benefit from transactions: only queue a job if the related data is 100% guaranteed to have been written to the database, in such a way that it's not possible for the queue entry not to be written.

Brandur wrote a great piece about a related pattern here: https://brandur.org/job-drain

He recommends using a transactional "staging" queue in your database which is then written out to your actual queue by a separate process.

這也是當年為什麼用 MySQL 幹類似的事情,要 ACID 的特性來確保內容不會掉。

這也是目前我覺得唯一還需要用 RDBMS 當 queue backend 的地方,但原文公司的想法就很迷,遇到 library bug 後決定換架構,而不是想辦法解 bug,還很開心的寫一篇文章來宣傳...

npm 裡的 redis 與 ioredis

前幾天在噗浪的偷偷說上看到有人提到 npmtrends 上的 redis (官方的) 與 ioredis:「https://www.plurk.com/p/p6wdc9」。

意外發現以下載量來看,ioredis 已經超越官方的 redis 了:

找了一下差異,看起來的確有些團隊在 loading 很高的情況下會考慮用 ioredis 取代 redis:「Migrating from Node Redis to Ioredis: a slightly bumpy but faster road」。

但沒有特別需求的話應該還是會用官方版本?