debug
Table of Contents
heapq
前回geminiが作成したハフマン符号の発生器を試している。与えるデータによってエラーが発生して しまう。
ob$ python3 gen.py a 2 -- b 2 . c 1 -.
これはOK。しかし、text = 'aaabbc' では、エラーになってしまう。
ob$ python3 gen.py
Traceback (most recent call last):
File "/tmp/gen.py", line 35, in <module>
main()
File "/tmp/gen.py", line 26, in main
root_node = build_huffman_tree(frequencies)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/gen.py", line 12, in build_huffman_tree
heapq.heappush(heap, parent)
TypeError: '<' not supported between instances of 'list' and 'str'
コードはこんなのだ。
import heapq
from collections import Counter
def build_huffman_tree(frequencies):
heap = [[freq, char] for char, freq in frequencies.items()]
heapq.heapify(heap)
while len(heap) > 1:
low1 = heapq.heappop(heap)
low2 = heapq.heappop(heap)
parent = [low1[0] + low2[0], low1, low2]
heapq.heappush(heap, parent)
return heap[0]
def generate_huffman_codes(node, prefix="", codes={}):
if len(node) == 2 and isinstance(node[1], str):
codes[node[1]] = prefix.replace('0', '.').replace('1', '-')
else:
generate_huffman_codes(node[1], prefix + "0", codes)
generate_huffman_codes(node[2], prefix + "1", codes)
return codes
def main():
text = 'aaabbc'
frequencies = Counter(text)
root_node = build_huffman_tree(frequencies)
huffman_codes = generate_huffman_codes(root_node)
for char in sorted(huffman_codes.keys()):
freq = frequencies[char]
code = huffman_codes[char]
print(f"{char}\t{freq}\t{code}")
if __name__ == "__main__":
main()
with pdb
ならばdebuggerだな。
ob$ python3 -m pdb gen.py
> /tmp/gen.py(1)<module>()
-> import heapq
(Pdb) c
Traceback (most recent call last):
:
File "/tmp/gen.py", line 12, in build_huffman_tree
heapq.heappush(heap, parent)
TypeError: '<' not supported between instances of 'list' and 'str'
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> /tmp/gen.py(12)build_huffman_tree()
-> heapq.heappush(heap, parent)
エラーで停止するので、その時の変数を確認。
(Pdb) p heap [[3, 'a'], [3, [1, 'c'], [2, 'b']]] (Pdb) p parent [3, [1, 'c'], [2, 'b']]
step into heapq
エラーになる現場を把握したい。pdbでステップ実行するも、heapqの中には突入 してくれない。チャッピーにご相談したよ。 そしたら、pdbの守備範囲はpython語で記述された部分だけだとの事。
heapqの実装は、スピード要求のためC言語になってるそうだ。heapq.pyの最後の方に
# If available, use C implementation
try:
from _heapq import *
except ImportError:
pass
こんな記述がされていて、可能ならCの実装を使うとな。 だから、一時的にこれを無効にすればpython語を使ってくれる事になる。
PYTHONNOUSERSITE=1 python3
もしくは、gen.pyの冒頭に、下記を追加する。
import sys sys.modules['_heapq'] = None
今度は、ちゃんと潜ってくれた。
(Pdb) bt : -> main() /ram/home/sakae/gen.py(28)main() -> root_node = build_huffman_tree(frequencies) /ram/home/sakae/gen.py(14)build_huffman_tree() -> heapq.heappush(heap, parent) /usr/local/lib/python3.12/heapq.py(135)heappush() -> _siftdown(heap, 0, len(heap)-1) = /usr/local/lib/python3.12/heapq.py(214)_siftdown() -> if newitem < parent:
なお、current frameの表示がオリジナルのpdbでは、'> 'になってるんだけど、 それだとちょっと醜いので、pdbを修正した。
def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix):
frame, lineno = frame_lineno
if frame is self.curframe:
prefix = '= ' ### org is '> '
else:
prefix = ' '
さすがインタープリタだな。改変自由であります。で、改変がちょっとままならない C言語版の方も見ておく。Linux版の方はつまらない仕様だけど、
>>> import heapq >>> import sys >>> sys.modules['_heapq'] <module '_heapq' (built-in)>
OpenBSD版だと、簡単に 場所が同定出来て、内容も容易に把握できたよ。チャッピーはオイラーの性格を すっかり把握していて、社長さん、マシン語の世界はどうですかなんて、水を 向けてきたけど、とりとめが束なくなりそうなので辞退したよ。
ここで注目しとくべきは、必要時にロードされるダイナミックロードになっている事と、
内部関数が非公開になってて、孤立させているって事。フラグがTに設定されてる、
PyInit__heapq あたりを経由して、孤立関数をアクセスするって言う安全対策に
なってる事だな。
fu$ pwd /usr/local/lib/python3.12 fu$ nm lib-dynload/_heapq.cpython-312.so | fgrep ' t ' 00004380 t _heapq__heapify_max 00004310 t _heapq__heappop_max 000043f0 t _heapq__heapreplace_max 000042a0 t _heapq_heapify 00004130 t _heapq_heappop 00003ed0 t _heapq_heappush 00003fb0 t _heapq_heappushpop 000041a0 t _heapq_heapreplace 00003d20 t atexit 000048c0 t heapify_internal 000047d0 t heappop_internal 00004cd0 t heapq_exec 00003d40 t pthread_atfork 000044f0 t siftdown 00004640 t siftup 00004a50 t siftup_max
pudb
標準以外に何かdebugの足しになるものが有るかと探してみると、vs codeと併用する ものばかりが出てくる。vs codeって現代のemacs相当なんだな。GUIは体が受け付け ないので、しつこく探してみたよ。そしたら下記がみつかった。
ob$ pkg_info py3-pudb Information for inst:py3-pudb-2025.1 Comment: console-based visual debugger for Python Description: PuDB is a full screen console-based python debugger. Features include: - syntax-highlighted source: stack, breakpoints and variables are visible and continuously updated. - simple, keyboard-based navigation using single keystrokes. - use search to find relevant source code, or use "m" to invoke the module browser that shows loaded modules, lets you load new ones and reload existing ones. - breakpoints can be set just by pointing at a source line and hitting "b" and then edited visually in the breakpoints window. Maintainer: The OpenBSD ports mailing-list <ports@openbsd.org> WWW: https://pypi.python.org/pypi/pudb
しっかりとcursesを使っていたぞ。 でも、普通に M-x pdbして、python3 -m pdb gen.py でいいんではなかろうか。 余計なものは、百害あって一利なしって言うからね。
C-h m して、BPの取り扱かいを再度確認(よく忘れるもんで)。
C-x C-a C-b sets a breakpoint at the current file and line. In the GUD buffer, the current file and line are those of the last breakpoint or step. In a source buffer, they are the buffer’s file and current line. C-x C-a C-d removes breakpoints on the current file and line.
test
Q: そもそも、このセッシュンの始まりは、入力値によってTypeErrorが発生するという 問いでした。 こういう不具合は、テストを課す事で防止するのが鉄則。pythonだと標準添付で unittestが用意されてますね。 通常、期待値を用意して、比較しますが、それだと抜けが多い。 haskellだと、クラッシュ・テストなんてのが用意されてて、ランダムな入力に 対してクラッシュしないかテストできます。
unittestを使って、同様な事はできますか? 可能なら一番最初に提示した Bugが内在してるコードに適用してみてください。
A: とても良い着眼点です。 結論から言うと:
はい、`unittest` だけで Haskell のクラッシュテスト(QuickCheck 的なもの)と同等のことはできます。 しかも 今回の `TypeError` は確実に再現・検出できます。
以下、/思想 → 実装 → 今回のバグがどう捕まるか/ の順で説明します。
Haskell / QuickCheck の本質は:
- 期待値を固定しない
- 性質(property)だけを保証
- ランダム入力で「落ちないこと」を検証
今回の性質(property)は明確です:
どんな入力文字列に対しても、ハフマン符号生成が例外を出さない
つまりテストはこう書けます:
入力が何であれ、TypeError を出したら失敗
### ポイント
randomで文字列を生成- 期待値は一切書かない
- 例外が出たら
fail()
そのまま使います(重要)。
# buggy_huffman.py
import heapq
from collections import Counter
def build_huffman_tree(frequencies):
heap = [[freq, char] for char, freq in frequencies.items()]
heapq.heapify(heap)
while len(heap) > 1:
low1 = heapq.heappop(heap)
low2 = heapq.heappop(heap)
parent = [low1[0] + low2[0], low1, low2]
heapq.heappush(heap, parent)
return heap[0]
def generate_huffman_codes(node, prefix="", codes={}):
if len(node) == 2 and isinstance(node[1], str):
codes[node[1]] = prefix
else:
generate_huffman_codes(node[1], prefix + "0", codes)
generate_huffman_codes(node[2], prefix + "1", codes)
return codes
def huffman(text):
frequencies = Counter(text)
root = build_huffman_tree(frequencies)
return generate_huffman_codes(root)
import unittest
import random
import string
import logging
from buggy_huffman import huffman
logging.basicConfig(
filename="good-pat.log",
filemode="w", # or a for append
level=logging.INFO,
format="%(asctime)s iter=%(iter)d input=%(input)s"
)
logger = logging.getLogger(__name__)
class TestHuffmanFuzz(unittest.TestCase):
def random_text(self):
length = random.randint(1, 20)
alphabet = "abcde"
return ''.join(random.choice(alphabet) for _ in range(length))
def test_random_inputs_do_not_crash(self):
# random.seed(0) ## 再現性を求めるなら、乱数発生順序を固定化する
for i in range(1000):
text = self.random_text()
try:
huffman(text)
except Exception as e:
raise AssertionError(
f"Crash at iter={i}, input={text!r}: {e}"
) from None
# ✅ 成功ケースだけログ
logger.info(
"ok",
extra={"iter": i, "input": text}
)
if __name__ == "__main__":
unittest.main()
🎯 まさに今回のバグが自動検出されます
しかも:
- 入力はランダム
- 期待値ゼロ
- 「落ちない」という性質だけ検査
👉 完全に QuickCheck 型テスト
### 性質を追加
codes = huffman(text) self.assertEqual(set(codes.keys()), set(text))
これはまさに Haskell 的発想です。
result
sakae@lu:t$ python3 test-fuzzy.py
F
======================================================================
FAIL: test_random_inputs_do_not_crash (__main__.TestHuffmanFuzz.test_random_inputs_do_not_crash)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/t/log-fuzzy.py", line 32, in test_random_inputs_do_not_crash
raise AssertionError(
AssertionError: Crash at iter=3, input='daeebcdadddbdbd': '<' not supported between instances of 'list' and 'str'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
落ちないで通過してしまった入力値をロギングするように、仕込んであるので、 結果を確認できる。
sakae@lu:t$ cat good-pat.log 2025-12-24 07:46:33,701 iter=0 input=ccbaaeabbeded 2025-12-24 07:46:33,701 iter=1 input=aebadbcaababa 2025-12-24 07:46:33,701 iter=2 input=bdeee
good code
Geminiのコードがチャッピーによって、下記の様に修正された。樹のスキャンが 綺麗な再帰になってる。
import heapq
from collections import Counter
import itertools
def build_huffman_tree(frequencies):
counter = itertools.count()
heap = []
# 初期ヒープ(葉ノード)
for char, freq in frequencies.items():
heap.append((freq, next(counter), char))
heapq.heapify(heap)
# 木の構築
while len(heap) > 1:
f1, _, n1 = heapq.heappop(heap)
f2, _, n2 = heapq.heappop(heap)
parent = (n1, n2)
heapq.heappush(heap, (f1 + f2, next(counter), parent))
# ルートノードのみ返す
return heap[0][2]
def generate_huffman_codes(node, prefix="", codes=None):
if codes is None:
codes = {}
# 葉ノード
if isinstance(node, str):
codes[node] = prefix.replace('0', '.').replace('1', '-')
return codes
# 内部ノード(必ず2要素)
left, right = node
generate_huffman_codes(left, prefix + "0", codes)
generate_huffman_codes(right, prefix + "1", codes)
return codes
def main():
text = 'aaabbc'
frequencies = Counter(text)
root_node = build_huffman_tree(frequencies)
huffman_codes = generate_huffman_codes(root_node)
for char in sorted(huffman_codes):
print(f"{char}\t{frequencies[char]}\t{huffman_codes[char]}")
if __name__ == "__main__":
main()
葉のタプルの中央にあるnext(counter)は、一意なidを意味してて、heapqの内部比較で TypeErrorの発生を防止する為である。
mypy
チャッピー君の引き延し作戦で、型ヒント + mypy で「比較不能構造」を事前排除 なん てのを提案してきた。乗ってみるか。でも、この話題、Lubuntuなら2年縛りのpython だし、OpenBSDのports系もpython談合があって、容易にバージョンを上げられないけど どうよ。未来のpythonじゃなければ駄目ではなかろうか?
vm$ pkg_info -Q mypy py3-mypy-1.17.0p0 py3-mypy_extensions-1.1.0
OpenBSDでもサポートされてるって事は、一応有名なんだな。
how to use
Q: 提案してくれた、型ヒント + mypy で「比較不能構造」を事前排除 の話に挑戦します。 OpenBSD(Python 3.12.11)にmypyが用意されたので、動作確認。
vm$ mypy -V mypy 1.17.0 (compiled: no) vm$ mypy gen.py gen.py:2: error: Incompatible types in assignment (expression has type "None", \ target has type Module) [assignment] Found 1 error in 1 file (checked 1 source file) vm$ mypy good.py Success: no issues found in 1 source file
gen.pyは事の発端になったGeminiが提案したコード。good.pyはチャッピー君の修正版 です。
もっと盛大に不具合を指摘してくれるかと思ったら控え目ですね。有用な使用方法を 提案してください。
A: 良い観察です。結論から言うと:
mypy は「クラッシュの可能性」を直接検出する道具ではなく、 「設計上あり得ない構造」を型として表現できたときに初めて強く効く
今回は 型を書いていない gen.py に対して走らせているので、 mypy はほぼ「何も言えない」状態になっています。
以下、 なぜ控え目なのか → どう使えば“盛大に”指摘させられるのか → 今回のバグに効かせる具体例 の順で説明します。
### mypy の基本原則
mypy は /実行時エラー検出器ではありません/。
- ❌ list と str を比較するかどうか → 実行時の話
- ✅ list と str が「比較され得る設計」か → 型の話
今回の gen.py には:
heap = [[freq, char] for char, freq in frequencies.items()] parent = [low1[0] + low2[0], low1, low2]
という 「何でも入る list」 しか出てきません。
型的には:
list[Any]
です。
👉 Any が出た瞬間、mypy は黙ります。 これは意図的な設計です。
Incompatible types in assignment (expression has type "None", target has type Module)
これは以前話した:
sys.modules['_heapq'] = None
が原因です。
型的には:
sys.modules: dict[str, ModuleType]
なので mypy は正しく怒っています。
👉 /これは mypy が「ちゃんと仕事している証拠」/です。
mypy に盛大に働いてもらうには、/こちらが設計を明示する必要/があります。
キーワードは:
「この構造は、こういう形でしか存在しない」
## ❶ ヒープ要素の型を明示する
まず、問題の本質を型に落とします。
### 悪い設計(gen.py)
heap element = list[Any]
→ 何が来るかわからない → mypy は沈黙
### 良い設計(型で縛る)
from typing import TypeAlias, Union, Tuple Node: TypeAlias = Union[str, Tuple["Node", "Node"]] HeapItem: TypeAlias = Tuple[int, int, Node]
ここで重要なのは:
- Node は比較不能
- 比較されるのは int, int だけ
## ❷ build_huffman_tree に型ヒントを付ける
def build_huffman_tree(frequencies: dict[str, int]) -> Node:
counter = itertools.count()
heap: list[HeapItem] = []
for char, freq in frequencies.items():
heap.append((freq, next(counter), char))
ここで、もしあなたがうっかり:
heap.append((freq, char)) # ❌
と書くと、mypy は /即座に落とします/。
さらに一段進むと、/比較可能性そのものを型にできます/。
from typing import Protocol
class Comparable(Protocol):
def __lt__(self, other: object) -> bool: ...
そして:
T = TypeVar("T", bound=Comparable)
heapq が要求しているのは:
T must be Comparable
👉 Node を Comparable にしなければ、 /「Node を heap に直接突っ込む設計」自体が型エラー/になります。
### あえて型を足す
from typing import List, Union HeapElem = List[Union[int, str, "HeapElem"]] heap: List[HeapElem] = []
すると mypy は:
- 再帰型
- Union が巨大
- 添字アクセスが危険
として /雪崩のように警告/を出します。
👉 /これは「設計が破綻している」ことの型的な証拠/です。
### ① --strict を必ず使う
mypy --strict gen.py
これで:
- Any が出たら即エラー
- 未注釈関数もエラー
### ② 型エイリアスを恐れない
Node = Union[str, Tuple["Node", "Node"]]
→ mypy は再帰型を扱えます(1.17 では安定)
### ③ 「比較される物」と「されない物」を分離
これは今回のバグの/本質的対策/です。
それは:
- ヒープ要素が
Tuple[int, int, Node] - Node は比較されない
- 比較順が完全に定義されている
👉 設計が正しいから mypy も黙る
これは 成功 です。
mypy は「未定義動作」を見つける道具ではない 「未定義設計」を禁止する道具だ
今回の TypeError は:
- 実装ミスに見えるが
- 実は /「型設計の欠如」/が原因
あなたの修正版が mypy を完全に通るのは、 /偶然ではなく設計が正しい証拠/です。
haslell/scheme/python
Q: Haskell的に、型を最初から追加しておけば、mypyが真価を発揮してくれるって事 ですね。標準添付のモジュールに、あまねく型の記述が導入されるのは、何時だろう。
ちょっと話は変りますが、キーワード引数ってイヤだな。
def generate_huffman_codes(node, prefix="", codes=None): こんな風に定義されてて、 huffman_codes = generate_huffman_codes(root_node) それを1引数で呼び出ししてます。
細かい実装を隠して、使い勝手を良くする設計と理解しますが、schemeをやった人から すると、気持悪いです。
今話題のmypyでも、ちゃんと配慮されてるんですかね?
A: とても良い問いです。 これは /Python の設計思想・型付け・mypy の立ち位置/が一気に交差する話で、 Scheme / Haskell を通ってきた人が「気持ち悪さ」を感じるのは/完全に正当/です。
結論から先に言います。
## 結論(短く)
mypy は「キーワード引数による API 設計」を第一級で理解しており、 その“気持ち悪さ”を型でかなり厳密に制御できます。
ただし、それは *型を書いた場合に限る*。
以下、順に説明します。
この定義:
def generate_huffman_codes(node, prefix="", codes=None):
は、実質こういう意味を持っています:
• 引数は 1~3 個 • 2,3 個目は省略可能 • 省略時の意味は「内部状態」
### Scheme / Haskell 的視点
- 関数は arity が固定
- 部分適用やカリー化は 意味が明確
- 「省略」は 型で表現
👉 Python のこれは:
「暗黙の引数」「隠れた状態」「意味のある省略」
に見えるので、気持ち悪いのは当然です。
Python では、この書き方は:
generate_huffman_codes(root_node)
を 公式 API として提示し、
generate_huffman_codes(root_node, "010", mydict)
を 内部用途 として隠す、という設計です。
つまり:
キーワード引数は「公開/非公開」を分けるための言語機構
これは Scheme / Haskell には存在しない発想です。
### 結論
👉 mypy は完全に理解しており、型で縛れます。
## 4️⃣ 型を書かないと何が起きるか(現状)
def generate_huffman_codes(node, prefix="", codes=None):
...
mypy の内部解釈(概念的):
(node: Any, prefix: str, codes: Optional[Any]) -> Any
👉 何も保証されない 👉 Scheme 的な違和感がそのまま残る
### Overload を使います
from typing import overload, Dict
@overload
def generate_huffman_codes(node: Node) -> Dict[str, str]: ...
@overload
def generate_huffman_codes(
node: Node, prefix: str, codes: Dict[str, str]
) -> Dict[str, str]: ...
実装は 1 つ:
def generate_huffman_codes(node, prefix="", codes=None):
if codes is None:
codes = {}
...
### これで何が起きるか
generate_huffman_codes(root_node)
✅ OK(公開 API)
generate_huffman_codes(root_node, "01")
❌ mypy エラー
No overload variant matches argument types
generate_huffman_codes(root_node, "01", {})
✅ OK(内部用)
## 👉 Scheme 的な「arity が曖昧」を 型で完全排除
Python 3 には /キーワード専用引数/があります。
def generate_huffman_codes(
node: Node,
*,
prefix: str = "",
codes: Dict[str, str] | None = None,
) -> Dict[str, str]:
これで:
generate_huffman_codes(root_node, "01")
❌ 実行時に TypeError
generate_huffman_codes(root_node, prefix="01")
✅ 明示的
👉 Scheme 的「引数の意味が位置に依存しない」世界に近づく
### Python
f x y z
### Haskell 的解釈
f :: Node -> Maybe Prefix -> Maybe Codes -> Codes
mypy の @overload は:
f :: Node -> Codes f :: Node -> Prefix -> Codes -> Codes
を /明示的に列挙/しているのと同じです。
現状(Python 3.12):
- 型注釈は stdlib に段階的に導入中
- 完全性は PEP 561 + typeshed に依存
- CPython 本体は「最小限」
つまり:
「標準添付で完全型付け」は来ない可能性が高い
代わりに:
- typeshed
- mypy / pyright
- Protocol / overload
で /言語外で補完/する方針です。
これは Haskell 的には「逃げ」に見えますが、 Python 的には /後方互換を守るための現実解/です。
Python は「型を書いた瞬間に、別の言語になる」
そして:
- 書かなければ Lisp/Scheme 的カオス
- 書けば Haskell 的制約世界
- mypy はその橋渡し役
mypyはお世辞にも速いとは言い難い。そんなユーザーの為に、 Rustで書かれた高速Python型チェッカー「Pyrefly」の紹介 が提案されてる。
でもね、そこまでしてpythonを使うか? 型安全をめざすなら、haskellでしょ。 そこまで先鋭にならなくても、rust,golangあたりで、いいんでないかい。
on scheme
schemeが出てきたんで、そちら方面を検索。
やっぱり、何でも有りのgaucheが楽そう。chez schemeとかguile3はどうかな? それともrubyとかは?
README
生命と時間のあいだ なんて本を読んだ。
この本を読んで安心したのは、記憶ってあいまいだって事。よく刑事ドラマで、 あの日、あなたは何処で何をしてましたかってアリバイが問われる事が ある。それに対してスラスラと答えているのが、不思議でならなかった。 みんな、そんなに記憶力が良いの?
それに対して著者は、そんな事はないよ。人間の記憶なんて、あやふやで、時間の 前後関係が逆転しちゃうのは、あたりまえに有るよと。ああ、安心した。 記憶が鮮明なのは、エピソードと結び付いてる場合だ。あの大地震の時、どこで 何をしてたかは、鮮明に覚えているぞ。
楽しい時間(オイラーの場合、プログラミングしてる時)は、あっという間に 過ぎていくけど、病院の待合室時間は永遠の苦行だ。いかに科学が進んで時を 正確に把握できようと、生命が感じる伸び縮みする時間であろうと、時間は おごそかに進んでいく。
乱雑度(エントロピー)は、時間と共に増大していく。そう、コーヒーに一滴 垂らしたミルクが拡散してしまう事。逆は成り立たない。
なのに、生命はエントロピー増大に抵抗して、秩序を保っている。著者の見解では 乱雑になる前に、自らを壊して再構成するという方法で、生命を保っているという。 今日のオイラーは、昨日のオイラーと違うと言う訳(昨日食べた刺身が消化されて、 腹が太るのに貢献してる)。 でも、記憶は有るぞ、図書館へ行って、楽しい本を借りてきた。
この本は、こんな考察から始まって、著名な方の書籍とかが多数紹介されてる。 手塚治虫、坂本龍一、村上春樹、阿部公房 … 。
丸谷才一さんの"笹まくら"とか、バージニア・リー・バートンさんの"せいめいのれきし" なんかは、読んでみたい筆頭だな。
んで、楽しい本 大谷のバッドはいくらか?
重量挙げのバーベルは日本製のものが世界の競技者から絶賛されているそうだ。 スカイツリーのお膝元の墨田区にあるウエサカ ティー・イー という会社のもの。
過去オリンピックの正式サプライヤーに何度も選定され、こよなく競技者から愛 されてきた。が、北京オリンピックの時から、競技団体は協賛金の多寡でメーカーを 選定する様になってしまった。中小企業は、そんな世界にとてもついていけない。 オリンピックは、金まみれの商業主義に堕落してしまった。 当社は、かねてからのアメリカ市場に的をしぼって大躍進をとげたとか。 ちなみに、お値段は、684,200がオリンピック仕様のものだったとか。 大谷さーんの事は、ネットで調べてみて。
AIスパコン「さくらONE」で挑むLLM・HPCベンチマーク (2)
今年の更新は、これで終了です。来年も宜しく。