clear

Table of Contents

cuda

巻末のREADMEでエヌビディアを取り上げたんで、そこら辺の技術を探ってみる。

CUDAプログラミング第一歩 とっても面倒そうなので、普通は PyTorch なんかの革をまとうのかな。

GPUサーバのインターコネクト:InfiniBand vs イーサネット完全解説

v シェーダー for Vlang グラフィックの入口で良く聞くな

並行計算 for Vlang

module main

import gg
import gx

fn main() {
    mut context := gg.new_context(
        bg_color:     gx.rgb(174, 198, 255)
        width:        600
        height:       400
        window_title: 'Polygons'
        frame_fn:     frame
    )
    context.run()
}

fn frame(mut ctx gg.Context) {
    ctx.begin()
    ctx.draw_convex_poly([f32(100.0), 100.0, 200.0, 100.0, 300.0, 200.0, 200.0, 300.0, 100.0, 300.0],
        gx.blue)
    ctx.draw_poly_empty([f32(50.0), 50.0, 70.0, 60.0, 90.0, 80.0, 70.0, 110.0], gx.black)
    ctx.draw_triangle_filled(450, 142, 530, 280, 370, 280, gx.red)
    ctx.end()
}

OpenGLをかすかに思い出した。これが発展してくと描画エンジンがグラフィック・ボード の載る。サイズの変更やら回転が高速で可能。回転なんてのは行列で定義されてる。 しかるに、グラボがAI用の計算エンジンになるんじゃねぇ。だったら使い易いソフトも 一緒に提供しよう。その名称は、cuda。更にAIに特化したライブラリィーも提供 しよう。その名称は、cuDNN。

河豚板の真似

鬼門だったインストール時のdiskの扱いが河豚板のusbfadmを読み解いて理解 できたので手動でやってみる。今はGPTの時代ですからねぇ。毎度のMBRだけじゃ 脳が無いです。まずは、4Gのファイルをddで作成しとく。それをvnconfigで diskに見立てる所から始まる。

ob# vnconfig vnd0 /home/sakae/mydisk
ob# fdisk -igy vnd0  ;; MBR付きでGPT形式にする
Writing GPT.
ob# fdisk -e vnd0    ;; diskを編集するぞ
Enter 'help' for information
vnd0: 1> p           ;; 現状の確認
Disk: vnd0       Usable LBA: 34 to 8191966 [8192000 Sectors]
GUID: 27be0eb0-1a15-40bb-99e3-561f6e04690b
   #: type                                 [       start:         size ]
      guid                                 name
------------------------------------------------------------------------
   0: OpenBSD                              [          64:      8191903 ]
      10f9df02-719d-4ba8-9cc4-c24dc9a052c7 OpenBSD Area
vnd0: 1> edit 0      ;; 0番さんを開放
   #: type                                 [       start:         size ]
------------------------------------------------------------------------
   0: OpenBSD                              [          64:      8191903 ]
Partition id ('0' to disable) [01 - FF, <uuid>]: [A6] (? for help) 0
Partition 0 is disabled.
vnd0*: 1> edit 1    ;; 1番さんにBIOSでも理解できるエリアを作成
   #: type                                 [       start:         size ]
------------------------------------------------------------------------
   1: Unused                               [           0:            1 ]
Partition id ('0' to disable) [01 - FF, <uuid>]: [00] (? for help) EF
Partition offset [34 - 8191966]: [34]
Partition size [1 - 8191933]: [8191933] 500m
Partition name: [] boot
vnd0*: 1> edit 2    ;; 2番さんにDOSエリアを設定。他OSとの回廊用
   #: type                                 [       start:         size ]
------------------------------------------------------------------------
   2: Unused                               [           0:            1 ]
Partition id ('0' to disable) [01 - FF, <uuid>]: [00] (? for help) c
Partition offset [34 - 8191966]: [1024034]
Partition size [1 - 7167933]: [7167933] 500m
Partition name: [] dos
vnd0*: 1> edit 3    ;; 最後はOpenBSDのエリア
   #: type                                 [       start:         size ]
------------------------------------------------------------------------
   3: Unused                               [           0:            1 ]
Partition id ('0' to disable) [01 - FF, <uuid>]: [00] (? for help) a6
Partition offset [34 - 8191966]: [2048034]
Partition size [1 - 6143933]: [6143933]
Partition name: [] bsd
vnd0*: 1> p        ;; 編集の成果
Disk: vnd0       Usable LBA: 34 to 8191966 [8192000 Sectors]
GUID: 27be0eb0-1a15-40bb-99e3-561f6e04690b
   #: type                                 [       start:         size ]
      guid                                 name
------------------------------------------------------------------------
   1: EFI Sys                              [          34:      1024000 ]
      fedfde66-5289-41c4-8466-ab0ec7b27eaa boot
   2: Microsoft basic data                 [     1024034:      1024000 ]
      6ea9e9bf-1161-4841-accd-a4259458bf10 dos
   3: OpenBSD                              [     2048034:      6143933 ]
      d696fbde-808c-46f2-90d5-28208eddea71 bsd
vnd0*: 1> w        ;; 書き込んで終了
Writing GPT.
vnd0: 1> quit

次はOpenBSD用のエリアの区画を用意してく

ob# disklabel -E vnd0
Label editor (enter '?' for help at any prompt)
vnd0> p            ;; OpenBSDからは、こんな風にdiskが認識されてる。
OpenBSD area: 2048034-8191967; size: 6143933; free: 59
#                size           offset  fstype [fsize bsize   cpg]
  c:          8192000                0  unused
  i:          1024000               34   MSDOS
  j:          1024000          1024034   MSDOS
vnd0*> a b        ;; 小さなswapエリアを用意
offset: [2048034]
size: [6143933] 128m
FS type: [swap]
vnd0*> a a        ;; 残りをOpenBSD用に割り当て
offset: [2310200]
size: [5881767]
FS type: [4.2BSD]
vnd0*> p
OpenBSD area: 2048034-8191967; size: 6143933; free: 39
#                size           offset  fstype [fsize bsize   cpg]
  a:          5881728          2310208  4.2BSD   2048 16384     1
  b:           262166          2048034    swap
  c:          8192000                0  unused
  i:          1024000               34   MSDOS
  j:          1024000          1024034   MSDOS
vnd0*> w         ;; 書き込んでから終了
vnd0> q
No label changes.

最後に、aパーテションを整地する。

ob# newfs vnd0a
/dev/rvnd0a: 2871.9MB in 5881728 sectors of 512 bytes
15 cylinder groups of 202.50MB, 12960 blocks, 25920 inodes each
super-block backups (for fsck -b #) at:
 160, 414880, 829600, 1244320, 1659040, 2073760, 2488480, 2903200, 3317920,
 3732640, 4147360, 4562080, 4976800, 5391520, 5806240,
ob# mount /dev/vnd0a /mnt  ;; マウントできればOK
ob# df -k
Filesystem  1K-blocks      Used     Avail Capacity  Mounted on
 :
/dev/vnd0a    2843102         2   2700946     1%    /mnt

clear, tput

前回やった端末をクリアーするコマンドが通常用になってたので確認してみる。

ob$ which clear
/usr/bin/clear
ob$ file /usr/bin/clear
/usr/bin/clear: ELF 32-bit LSB shared object, Intel 80386, version 1
ob$ ls -l /usr/bin/clear
-r-xr-xr-x  2 root  bin  22272 Sep 30  2024 /usr/bin/clear*

シェルスクリプトかと思ったら違ってたバイナリーでしかも他とリンクしてた。 そんなに立派なものか? 取りあえずソースに対面してみるか。。んが、そんなソース は無いぞ。他のコマンドに紛れ込んでいるんだな。iノードが同一なコマンドを 探してみるか。いや、今回は別な方法で行ってみる。

ob$ cd /usr/src/usr.bin
ob$ find . -name Makefile | xargs grep clear
./tput/Makefile:SRCS=   clear_cmd.c reset_cmd.c tparm_type.c tput.c transform.c \
./tput/Makefile:LINKS=  ${BINDIR}/tput ${BINDIR}/clear
./tput/Makefile:MAN=    tput.1 clear.1

見つけた。tputの類縁なのね。久しぶりにgdb出来る様にコンパイル。libcursesが内部的 に使われている。でそのcursesが端末情報のデータベースであるterminfoのラッパー みたいな位置付け。dbなんで元データを復元してソースレベルで取り込みたい。 んなもんで、ticなんてののお世話になっている。

ob$ doas make
cc -g -O0 -I/usr/src/usr.bin/tput/../../lib/libcurses -I/usr/src/usr.bin/tput/../tic -I/usr/src/usr.bin/tput -I. -Werror-implicit-function-declaration -MD -MP  -c /usr/src/usr.bin/tput/../tic/clear_cmd.c
cc -g -O0 -I/usr/src/usr.bin/tput/../../lib/libcurses -I/usr/src/usr.bin/tput/../tic -I/usr/src/usr.bin/tput -I. -Werror-implicit-function-declaration -MD -MP  -c /usr/src/usr.bin/tput/../tic/reset_cmd.c
cc -g -O0 -I/usr/src/usr.bin/tput/../../lib/libcurses -I/usr/src/usr.bin/tput/../tic -I/usr/src/usr.bin/tput -I. -Werror-implicit-function-declaration -MD -MP  -c /usr/src/usr.bin/tput/../tic/tparm_type.c
cc -g -O0 -I/usr/src/usr.bin/tput/../../lib/libcurses -I/usr/src/usr.bin/tput/../tic -I/usr/src/usr.bin/tput -I. -Werror-implicit-function-declaration -MD -MP  -c tput.c
cc -g -O0 -I/usr/src/usr.bin/tput/../../lib/libcurses -I/usr/src/usr.bin/tput/../tic -I/usr/src/usr.bin/tput -I. -Werror-implicit-function-declaration -MD -MP  -c /usr/src/usr.bin/tput/../tic/transform.c
cc -g -O0 -I/usr/src/usr.bin/tput/../../lib/libcurses -I/usr/src/usr.bin/tput/../tic -I/usr/src/usr.bin/tput -I. -Werror-implicit-function-declaration -MD -MP  -c /usr/src/usr.bin/tput/../tic/tty_settings.c
cc   -o tput clear_cmd.o reset_cmd.o tparm_type.o tput.o transform.o tty_settings.o -lcurses
ob$ doas ln tput clear

emacsからgdbすると、TERMが馬鹿端末としてターゲットが動作するんで、結果がエラーに なってしまう。裸のgdbを使うか、layout srcして少しはemacsの雰囲気で利用する事。 そして、特に意味もなく、qemu-kvmの環境で動作させた。TEFM=tmux-256color rows 34 が、Lubuntuの世界になってる。

Breakpoint 1, clear_cmd (legacy=false) at ../tic/clear_cmd.c:52
52          int retval = tputs(clear_screen, lines > 0 ? lines : 1, putch);
(gdb) bt
#0  clear_cmd (legacy=false) at ../tic/clear_cmd.c:52
#1  0x1443bc01 in tput_cmd (fd=2, settings=0xcf7d0b5c, argc=1,
    argv=0xcf7d1004, used=0xcf7d0b54) at tput.c:206
#2  0x1443b233 in main (argc=1, argv=0xcf7d1004) at tput.c:459
(gdb) l
47      }
48
49      int
50      clear_cmd(bool legacy)
51      {
52          int retval = tputs(clear_screen, lines > 0 ? lines : 1, putch);
53          if (!legacy) {
54              /* Clear the scrollback buffer if possible. */
55              char *E3 = tigetstr("E3");
56              if (E3)
(gdb) s
tputs (string=0x60b9a841 "\033[H\033[J", affcnt=34, outc=0x14438d30 <putch>)
    at /usr/src/lib/libcurses/tinfo/lib_tputs.c:454
454         SetSafeOutcWrapper(outc);

何やらエスケープシーケンス文字列が出てきたぞ。そして、少し丁寧に追跡。

 440         #if NCURSES_SP_FUNCS
 441         NCURSES_EXPORT(int)
 442         _nc_outc_wrapper(SCREEN *sp, int c)
 443         {
 444             if (0 == sp) {
 445                 return fputc(c, stdout);
 446             } else {
>447                 return sp->jump(c);
 448             }

こんな所でループしてる。

(gdb) bt 3
#0  _nc_outc_wrapper (sp=0xcf7cebbc, c=91)
    at /usr/src/lib/libcurses/tinfo/lib_tputs.c:447
#1  0x0620b743 in tputs_sp (sp=0xcf7cebbc, string=0x7e850042 "[H\033[J",
    affcnt=34, outc=0x620b930 <_nc_outc_wrapper>)
    at /usr/src/lib/libcurses/tinfo/lib_tputs.c:372
#2  0x0620b9e7 in tputs (string=0x7e850041 "\033[H\033[J", affcnt=34,
    outc=0x1a175d30 <putch>) at /usr/src/lib/libcurses/tinfo/lib_tputs.c:455

で、どんな文字列が送出されるか、トレースしてみる。fd 1 == stdout

te$ ktrace -ti clear
te$ kdump
  :
 28404 clear    GIO   fd 1 wrote 10 bytes
       "\^[[H\^[[J\^[[3J"

前回のtermでやったのでもOK。但しクリア後のカーソル位置が異なるけど。

te$ ktrace -ti printf '\x1b[2J'
te$ kdump
  :
 26489 printf   GIO   fd 1 wrote 4 bytes
       "\^[[2J"

これを受信したカーネルは、どんな応答をするのかな? wscons/wsemul_vt100.c あたりが基本になるのかな。

for OpenBSD

探ってみると、こんなのが出てくる。いかにも、っぽい。

vt100_handler *vt100_output[] = {
        wsemul_vt100_output_esc,
        wsemul_vt100_output_csi,
        wsemul_vt100_output_scs94,
        wsemul_vt100_output_scs94_percent,
        wsemul_vt100_output_scs96,
        wsemul_vt100_output_scs96_percent,
        wsemul_vt100_output_esc_hash,
        wsemul_vt100_output_esc_spc,
        wsemul_vt100_output_string,
        wsemul_vt100_output_string_esc,
        wsemul_vt100_output_dcs,
        wsemul_vt100_output_dcs_dollar,
        wsemul_vt100_output_esc_percent,
};

が、どれにもヒットしない。com1をconsoleに見立てているから? だったらtty系を 追跡してみるか。

(gdb) bt 6
#0  ttyoutput (c=13, tp=0xd23f9400) at /usr/src/sys/kern/tty.c:606
#1  0xd0756bcf in ttwrite (tp=0xd23f9400, uio=0xf0bb1434, flag=1) at /usr/src/s\
ys/kern/tty.c:1835
#2  0xd06b586c in comwrite (dev=2048, uio=0xf0bb1434, flag=1) at /usr/src/sys/d\
ev/ic/com.c:629
#3  0xd04d554b in spec_write (v=0xf0bb1380) at /usr/src/sys/kern/spec_vnops.c:3\
02
#4  0xd038cb79 in VOP_WRITE (vp=0xd226cd80, uio=0xf0bb1434, ioflag=1, cred=0xd2\
395e10) at /usr/src/sys/kern/vfs_vops.c:245
#5  0xd0346446 in vn_write (fp=0xd22f1724, uio=0xf0bb1434, fflags=0) at /usr/sr\
c/sys/kern/vfs_vnops.c:408

printf '\x1b[2J' を使ってみると、

(gdb) p cp
$1 = (u_char *) 0xf0b6f9cc "\033[2J<f\361\320P=}\317\001"
(gdb)

確かに来てる。

                                /*
                                 * If ce is zero, then we're processing
                                 * a special character through ttyoutput.
                                 */
                                if (ce == 0) {
                                        tp->t_rocount = 0;
=>                                      if (ttyoutput(*cp, tp) >= 0) {
                                                /* out of space */

んで、最後は、ここから抜けて行くんだけど、どうもすっきりしない。

done:
        if (obufcc)
=>              explicit_bzero(obuf, obufcc);
        return (error);

実戦検証の前に、机上検討を十分に実施した方が良さそうだ。 tty/pty/termios とかが鍵かな。

term on vinix

暫く間を置いてしまったけれどvlangによるLinuxの実装であるvinixでは、どうなって いるか? dev/consoleなんて言うピッタリなデバイスが有ったんで目を皿のようにして眺めて みたんだけど、それらしいのは見当らず。検索範囲を広めたら、 kernel/c/flanterm/README.md に、それらしい記述を発見。

# Flanterm

Flanterm is a fast and reasonably complete terminal emulator with support for
multiple output backends. Included is a fast framebuffer backend.

更にソースを眺めたら、真面目なmanが紹介されてた。 console_codes(4)

これで解決って事にしましょうかね。

for FreeBSD

man screen あたりが関係しそうなマニュアルで、ソースは、 syscons/scterm-sc.c

static void
scterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c)
{

        if (tcp->esc == 1) {    /* seen ESC */
                switch (c) {
                case '7':       /* Save cursor position */
                        tcp->saved_xpos = scp->xpos;
                        tcp->saved_ypos = scp->ypos;
                        break;
		:	
                case '[':       /* Start ESC [ sequence */
                        tcp->esc = 2;
                        tcp->last_param = -1;
                        for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
                                tcp->param[i] = 1;
                        tcp->num_param = 0;
                        return;

大変な解析を行なっているぞ。このdirの中にはスクリーン・セーバーのモジュールも 置いてあった。見てると楽しい。

README

The Nvidia Way エヌビディアの流儀

世界を席巻してるAIを下支えしてるGPU。 GPUと言えばNVIDIA。革ジャンの社長さんで有名。 何で革ジャンで登場する様になったかの説明は出てこなかったけど、同社の発展の 軌跡が熱く語られている。

こちらにハイライト の解説が掲載されてた。タイパやコスパ重視の方はどうぞ。

この会社、ブラック企業並に猛烈な働き方をするみたい。社員が逃避しない様に 株オプションと言う人参をチラつかせて、鼓舞してるそうだ。

社長さんは、随分長い事君臨してるけど、後継者の準備をちゃんとしてるのだろうか? この会社に期待してる金の亡者は、そんな事ばかり考えているようだ。


This year's Index

Home