SCALE:另外一個試著在 AMD GPU 上面跑 CUDA 程式的嘗試

昨天看到討論的蠻熱烈的東西,又是一個試著在 AMD GPU 上面跑 CUDA 程式的嘗試:「Run CUDA, unmodified, on AMD GPUs (scale-lang.com)」,連結的原文在「SCALE documentation」這邊。

跟之前提過的 ZLUDA 有些差異 (關於之前寫的紋章,可以參考「IntelAMD GPU 直接跑 CUDA 程式的 ZLUDA」這邊),在 ZCUDA 這邊是用 LD_PRELOAD 的方式達成的,像是 README 提到的這樣:

LD_LIBRARY_PATH="<ZLUDA_DIRECTORY>:$LD_LIBRARY_PATH" <APPLICATION> <APPLICATION_ARGUMENTS>

而從 SCLAE 的作法則是提供一整包編譯工具,讓你可以不用修改 CUDA 的程式,直接重新編就可以跑在 AMD GPU 上面,所以只能用在你有 source code 的情況下,並不是拿到 CUDA 程式的 binary 就可以跑。

算是個還蠻有趣的方法...

離跟 GIL 說再見更進一步的 Free-threaded CPython

在「Free-threaded CPython is ready to experiment with (quansight.org)」這邊看到 PythonGIL 的進度,從原文「Free-threaded CPython is ready to experiment with!」這邊可以看到有些需要套件一起配合的,像是 NumPy 這邊的「BUG: error Python 3.13 free-threaded RuntimeError: Identity cache already includes the item.」。

看起來用到 C 的實作 (大多數應該是為了加速,或是需要底層的 syscall) 都會需要注意一下。

另外值得一提的是目前拔掉 GIL 的版本在 single threading 的情況下會比標準版的 Python 3 慢很多,會需要後續再改進,所以一開始的版本就算穩定下來也可能沒有經濟上的效益,參考 id=40949628 這邊提到的:

Right now there is a significant single-threaded performance cost. Somewhere from 30-50%. Part of what my colleague Ken Jin and others are working on is getting back some of that lost performance by applying some optimizations. Expect single-threaded performance to improve for Python 3.14 next year.

另外有看到一些有趣的討論,像是為什麼不 bump 版本號碼到 Python 4 (因為語法沒有大改變?)。

C++ 實作高頻交易程式的技巧

看到「C++ patterns for low-latency applications including high-frequency trading (arxiv.org)」這篇,原文是 2023 年九月上傳到 arXiv 的 paper:「C++ Design Patterns for Low-latency Applications Including High-frequency Trading」。

有點 LLM 的文字感,在 Hacker News 上有人有提到這點,另外有一些圖表的錯誤,像是這兩份資料可以發現對不上,label 有標錯:

主要還是看列出的方法在自家專案上嘗試,不能直接把他們的數據拿來參考,在自家專案還是得在自家專案上面 benchmark 才知道有多少效益。

不過裡面提到蠻多有趣的作法,很多都是「知道」但沒有放在心上的...

dotenvx

清一清 tab... 兩個禮拜前還在日本時在 Hacker News 的「Show HN: From dotenv to dotenvx – better config management (dotenvx.com)」看到的東西,原文在推廣 dotenvx:「From dotenv to dotenvx: Next Generation Config Management」。

GitHub 的文件上可以看到幾個用法,一種是直接用,像是一般的 dotenv 的用法:

// index.js
require('@dotenvx/dotenvx').config()
console.log(`Hello ${process.env.HELLO}`)

另外一個是當 wrapper 用,像是這樣:

$ dotenvx run -- node index.js
Hello World # with dotenvx
> :-D

然後後者可以指定不同的 .env 多環境使用:

$ dotenvx run -f .env.production -- node index.js
[dotenvx][info] loading env (1) from .env.production
Hello production

另外還支援了 encrypt/decrypt 的能力降低 secret 的風險?不過這應該已經不是目前比較安全的方法了,這十年下來已經知道把 secret 放在環境變數裡太容易洩漏。

環境變數在呼叫外部程式時會被繼承,算是常見的 leaking 管道,另外就算不考慮外部程式,也會遇到環境變數算是一種全域變數,在寫測試時也很頭痛。

目前被提出來比較好的方法是把 secret 都放到 vault service 裡面,由 vault service 給一把讀取用的 API key,放進 dotenv 或是其他地方 (被稱為 secret zero)。

這樣這把 API key 去 vault service 抓取真正的 secret 放到程式內的物件取用 (像是資料庫的帳號密碼),而不是環境變數。

這樣做的 threat model 在 Hacker News 上有對應的討論,另外 AWS 的服務其實也做了類似的事情:「Amazon EC2 的 IMDSv2 計畫」。

所以 dotenvx 大概就看看,有個印象就好?

直接在 library 層將 MongoDB 用法轉換成 PostgreSQL 底層的 Pongo

看到這個「Mongo but on Postgres and with strong consistency benefits (github.com/event-driven-io)」算是另外一種用 PostgreSQL 取代 MongoDB 的嘗試,先前其他的方案是 proxy server 的方式實作 (像是 FerretDB),也就是 TCP 裡面傳的東西還是 MongoDB protocol,然後 proxy server 會轉譯成 PostgreSQL 的 SQL 語法。

這個作法的好處是不用管既有 application 是什麼程式語言開發的,另外改動比較少 (改個連線資訊 + 然後把目前還不支援的功能改寫),但缺點是多了一組 service 要維護 (如果是 HA 的話又還要設定 failover 或是 load balancer 的機制)。

Pongo 的作法則是移到 library 這邊做掉,所以就有程式語言的限制了:這個專案是用 TypeScript 開發,所以會是 JavaScript + TypeScript 生態系的方案。

不過好處就很明顯了,少了一組 service 要維護 (如果包括 HA 機制的話可能是兩組或三組),另外因為轉譯的部分在 application 端處理,沒有了 proxy server 也等於少了一個可能的 bottleneck。

這幾天上 Hacker News 後看 commit 頗熱鬧,從 Releases 頁可以看到連續出新版本。

不過... 不考慮直接用 PostgreSQL 嗎?

polyfill.io 被放 malicious code 的事件

台灣的圈子蠻多人是從「請儘速遠離 cdn.polyfill.io 之惡意程式碼淺析」這邊看到的,一些 code 相關的分析部分可以移駕過去看。裡面提到的 GitHub 上面 alitonium 所寫的 comment 蠻值得讀一下 (第一次點的時候會出現 GitHub 的警告,再點一次應該就會跳到正確的 comment 上)。

polyfill.js 算是老專案了,從 https://github.com/polyfillpolyfill/polyfill-service/graphs/contributors 這邊可以看到是 2013 年開始有記錄,主要是針對舊的瀏覽器 (像是 IE11),透過 javascript 的方式補上對應的功能。

現在的瀏覽器都是一直在更新,大多數的情況不太需要 polyfill 了,但畢竟很多舊的案子還在用,在這次 domain 被中國公司拿走後,Cloudflare 在今年 2024/2/29 就有先寫一篇算是預警的文章了:「polyfill.io now available on cdnjs: reduce your supply chain risk」,不過這種事情都是還沒發生前大家不會有太多重視,接下來就是 GitHub 上面的討論,然後是真的被動手加 malicious code 進去後,有人發現的討論。

後續大家都被迫要開始處理這件事情,GitHub 的作法看起來沒什麼問題:先標注 malicious repository 但是還是讓人可以進去翻歷史資料與討論。

不過 Cloudflare 這邊動作有點大,直接主動幫 CDN 客戶過濾了:「Automatically replacing polyfill.io links with Cloudflare’s mirror for a safer Internet」,這篇在 Hacker News 上也有討論:「Cloudflare automatically fixes Polyfill.io for free sites (cloudflare.com)」。

這個「越界」有點多,這應該也是直接讓 CEO Matthew Prince 出來掛文章作者的原因。這次 Cloudflare 主動做的事情包括了將免費的客戶預設開啟過濾,而付費的客戶則不會主動開啟,但提供一鍵開關:

Any website on the free plan has this feature automatically activated now. Websites on any paid plan can turn on this feature with a single click.

另外也允許所有客戶關掉這個保護:

All customers can turn off the feature at any time.

所以後續就會有另外一條大支線討論:在使用者沒有事前同意的情況下,以「安全」為名主動更改使用者頁面上的東西,這件事情是不是可以接受?如果以「安全」為名可以接受,為什麼是免費的先動,付費的卻不動?雖然我猜 Cloudflare 會裝死到底就是了...

Linux 上的 GNU sed 與 macOS 內的 sed 的 in-place 差異

結論:用 Perl

寫 shell script 的時候遇到的問題,在 Linux 上面使用 sed 換檔案裡面的字串,但不想要產生 backup file 的方式是:

sed -i -e 's/foo/bar/' example.txt

但在 macOS 內建的 sed 則是:

sed -i '' -e 's/foo/bar/' example.txt

也就是說前者 GNU sed 是處理 $1 (argv[1],anyway) 後面貼著的參數,而後者 macOS 的則是吃 $2 (argv[2]) 的參數。

Stack Overflow 上的「sed in-place flag that works both on Mac (BSD) and Linux」這邊有討論,看起來 sed 上沒有通解。

翻了 The Open Group 上的說明,sed 應該是定義在 POSIX 裡面,而從文件裡面沒有提到 backup file 可以知道這是各家自己實作的功能:「sed」。

所以一種解法是用 detection 的方式針對不同的 sed 給不同的指令;而另外一種解法是找其他工具。後者考慮到普及性,用 Perl 應該會是比較好的方式,目前不是 minimal 類的系統應該都還有 Perl 可以用:

perl -pi -e 's/foo/bar/' example.txt

但這樣跑在 CI 裡面的時候就得小心一點了,如果選到 minimal image 的話就會中獎... (煩躁?)

2012 年在 Google 時強制使用統一標準的 BUILD 檔案

Hacker News 上看到「Reformatting 100k Files at Google in 2011 (le-brun.eu)」這篇,原文在「The Story of Reformatting 100k Files at Google in 2012」這邊。

這篇除了作者寫的東西以外,Russ Cox 也在 Hacker News 上面分享了一些當時的背景。

故事是 2012 年的時候,作者 Laurent Le Brun (LinkedIn) 在德國,剛加入 Google 沒多久,負責處理 Google 內部的編譯工具 Blaze (外部稱 Bazel):

Back in September 2012, I was a junior engineer at Google, working on Bazel (Google’s build tool, also known internally as Blaze).

然後他與他的 team lead 收到美國團隊兩位工程師的會議邀請:

One day, a mysterious calendar invite landed in my inbox. It was sent by two engineers in the US, and I was invited along with my team lead.

然後這兩位是 Rob Pike 以及 Russ Cox:

I quickly recognized the names: Rob Pike and Russ Cox. Though I hadn't worked with them, I knew them by reputation: Russ Cox because I enjoyed reading his blog posts, and Rob Pike because, well… he’s famous.

作者這邊也懶得介紹 Rob Pike 了,畢竟是當年 Bell LabsPlan 9 的頭頭,然後又是 UTF-8 的發明人,後來在 Google 裡面也是 Go (程式語言) 的頭頭... 順便一提 Go 的吉祥物是他老婆畫的。

他們兩個人希望把全公司所有的 BUILD 檔案格式統一:

During the meeting, Rob and Russ shared their ambitious plan: to reformat every single Bazel BUILD file in Google’s codebase and enforce this formatting with a presubmit script.

中間有提到一些工程上的進行方式,但對我來說比較重要的是這幾個,首先是 Russ Cox 提到他在 Go 的團隊裡面學到的,(在大公司裡面) 不要讓工程師浪費時間在 formatting 之類的問題:

The formatting issue is a problem that should not exist and that we care enough about to spend our own engineering time eliminating it. I understand that it does not seem a priori that automated formatting would make a significant difference. I didn't truly understand it myself until we eliminated it from the Go code review and code editing processes. Hopefully in six months or a year, when everything is converted and we look back at this, the benefits will be clearer in retrospect.

另外在 update 的地方作者也提到了當時決定一次到位,把所有的 BUILD 檔案都修正完,而不是讓後續的人在更新時才強制要求,這樣可以避免後面的人接手的時候產生大量的 diff 而導致 review 困難:

Why not enable the new formatter without updating all the files? This would lead to long diffs whenever someone modifies a file, making the change hard to review. The cost would be spread over all the engineers in the company.

合併 GitHub Actions 的 IP address

GitHub 官方文件「About GitHub's IP addresses」中,是有提到 https://api.github.com/meta 這組 API endpoint,可以取得當下的 GitHub Actions 所使用的連外 IP address,不過如果你實際掃下來後會發現量相當大,以現在的情況來說,IPv4 address 有 3708 筆,IPv6 address 則有 801 筆:

$ cat github-actions-ipv4.txt | wc
   3708    3708   58233
$ cat github-actions-ipv6.txt | wc
    801     801   17522

實際去看的時候會看到一些吐血的,像是這包 /31 的:

13.105.49.0/31
13.105.49.2/31
13.105.49.4/31
13.105.49.6/31
13.105.49.8/31
13.105.49.10/31
13.105.49.12/31
13.105.49.14/31
13.105.49.16/31

這包還真的就整整 128 筆,你就不能輸出個 13.105.49.0/24 嗎...

ChatGPT 問了要怎麼解決,被提示有 netmask 這個工具可以用,不需要另外自己編譯,可以直接用 apt 裝起來然後倒進去讓他跑就好,整包搭配 jqHTTPie 處理掉 (換 curl 基本上也沒問題):

netmask --cidr -- $(http https://api.github.com/meta | jq -r '.actions[]')

Update:看到資安的朋友按讚突然想到,這邊用了 $() 把資料丟到 command line 包裝,可能會有安全上的顧慮,請自己斟酌...

不過整包 (IPv4 + IPv6) 還是有 3187 行,但總是有個方法可以整理起來用,不用自己刻一堆程式處理...

冼鏡光教授的「並行計算講堂」

在「Backend 台灣 (Backend Tw)」上看到冼鏡光教授的消息:(3257396121060908)

各位好

密西根理工大學資工系的冼鏡光教授,近期退休後將他的在學校授課時的並行計算(Concurrent Computing)課程、教材逐漸數位化,免費公開、分享給大家使用。

英文版的教材先前已全部製作完畢,近期教授正在努力製作中文版的部分,想讓台灣有興趣的工程師及學生比較不會受到語言的限制。

中文版的教材連結(目前更新至第二集):https://pages.mtu.edu/~shene/VIDEOS/CONCURRENT/index-TW.html

網頁在「【冼鏡光並行計算講堂】」;影片的部分是放到 YouTube 上面,可以參考 @ckshene7212/videos 這邊。

我們這個年代自學的 programmer 或多或少都有看過冼教授的書,不過畢業後看到冼教授的中文消息主要都是在攝影相關的領域,蠻開心可以看到教授退休後回來 CS 貢獻。

另外看了一下 html 頁面的寫法 (職業病?),沒有看到 doctype,大概是 html3 或是 html4 的用法,蠻有可能是教授自己用軟體弄的。

YouTube 頻道先訂閱起來,找時間翻一下影片...