5070Tiが良さそうだったのでついでに今までDDR5にするのを渋ってたメモリをアップグレードするかぁ!と総入れ替えした結果の記録。
グレードアップ現新比較表
デバイス | 変更前 | 変更後 |
---|---|---|
CPU | Intel Core i7 13700 | Intel Core Ultra 7 265F |
GPU | GeForce RTX 4070 Ti | GeForce RTX 5070 Ti |
MEM | Crucial Ballistix BL2K16G32C16U4B * 4 | Crucial CT2K16G56C46U5 * 4 |
M/B | ASUS TUF GAMING Z790-PLUS D4 | ASUS TUF GAMING Z890-PLUS WIFI |
今回はなんと、これだけのパーツを神戸市内、それも中央区だけで揃えてきた。通販は箱が増えて邪魔だし日本橋に行くのは大変なので、神戸で揃えられたのは非常に良かった。
組み換えシーン
机の下から薄汚れたケースを取り出すことから始まる。いい加減掃除した方がいいかなと思った。
まずは現環境をご開帳。1~2年に一度は簡単に掃除しているのもあり、中はそこまで汚れていない。
分解を進めていくときの部品入れに、いつか役に立つだろうと取っていた揖保乃糸の箱が役に立った。
グラボをメモリを外し、コネクタをいくらか外したところ。
CPUクーラーのヒートシンクもぼちぼち埃にまみれていた。これも掃除した方がいい。
CPUグリスは意外と乾いてなかった。このCPUを付けたのは2年半ほど前で、恐らくその時からそのままである。
オンボードLAN(Intel(R) Ethernet Controller I226-V)が腐っていたので取り付けた蟹のNICともお別れだ。新しいマザボのNICは蟹なので恐らく大丈夫という期待がある。
2025年7月2日追記
よく見たらNICはIntelで、相変わらず不安定だったため、結局蟹のNICをまた挿す羽目になった。Intel NICの不安定さについては別で記事にしようと思う。
ケースのフロントUSB用の拡張ボード。これも埃が積もっている。年期が入っているため、少しさびている気もする。
ケースからマザボを抜き取ったところ。まだNVMeSSDの抜去が残っている。マザボ交換は大変だ。
空っぽになったケース。よく見ると埃が積もっているので、やはり掃除が必要だ。
というわけで徹底的に掃除を始める。この後、全ての外装をはがし、ファンも外してクイックルワイパーとエアダスターでファンのフィンの一枚一枚や、わっか部分の内側など、掃除できる場所は掃除していった。
200mmファンの清掃ビフォーアフター。
裏配線の部分は比較的奇麗だったが、ここもクイックルワイパーやエアダスターを使って掃除していく。
一見そこまで汚れてなさそうな天面ファンも掃除する。
比較するとちゃんと奇麗になっている。こういうのは細かい積み重ねが大切なので、少しの埃であれ除去してゆく。
フロントパネルもはがして掃除する。
掃除している中でケースの前方下部にフィルターがあることに初めて気が付いた。電源ファン向けのフィルターだろうか?
今まで動かすときに何も考えずにつかんでいた気がするのでやや曲がっている。
完全に裸にして徹底的に掃除する。
戻していくところ。電源(PSU)を開けるのは地味に面倒なのだ。
新しいマザボには謎のパーツがたくさんついていたが、ほとんど使わなかった。ゴムだけ使った。
新しいマザボをケースにセットしたところ。ケーブルが多すぎて入れるのが大変だった。なお、この後のベンチマークの結果がイマイチで、元のマザボに戻し、またこのマザボに戻すという非常に面倒な工程を踏むハメになる…。
最近はNVMeが主流だからかSATAの数が少なかった。昔はもっとたくさんあったし、コネクタは一箇所に集中していて、こんな分散してなかったと思う。
細かいセッティングには、このようにケースの中に張り付いてくれる懐中電灯があると便利だ。ちなみにこれはヨドバシで売っている。
電源やリセットスイッチのケーブルを刺していて気が付いたが、このマザボにはブザーコネクタがなかった。LEDはあるものの、起動エラーを音で知れないのは少々不便である。
CPUを付けようとしたときにバックプレートが見当たらず探していたら、なんと前のマザボにセロテープでくっついていた。よく壊れなかったな…。
セロテープで固定していないと脱落してマウンタを付けづらいため、こうしていたのだと思うが、恐らくはがし忘れていたのだろう。
因みにこれはNoctuaのLGA1700用のバックプレートだが、LGA1851でもそのまま使うことができた。助かる。
マザボ現新比較。上側が今のマザボ、下が新しいマザボ。
新しい方がやや長く、薄くなっている。PCIeを複数使っている身としてはスリムになっているのは嬉しい。
PCIeスロット現新比較。左が今のマザボ、右が新しいマザボ。
今のマザボはボタンを押すとロックが外れる機構だが、ボタンが遠く、抜くとき斜めになりやすく、それが原因でロックが詰まることがしばしばあった。それに対して新しい方は位置が近いうえに、単純な作りになっており、こちらの方が抜き差ししやすいと感じた。押す場所が広く指が痛くならないのもいいところだ。
組み付け後。前よりちょっと高級感があり、チープ度が減った気がする。おそらくグラボのプラスチック感が減ったのが大きいだろう。
筐体もピカピカになっていい感じだ。しかしグラボのファンが光らなくなってしまったため回っているのか確認するのが少し煩わしくなってしまった。
セットアップ時に見舞われたトラブルの解消ログ
inaccessible boot driveというブルスクが出る
BIOSからIntel Rapid Storage TechnologyをOFFにする(デフォルトはOFF)
コマンドプロンプトで起動して以下のコマンドを流す。
sfc /scannow
OS起動時にAi Suite 3がaccess violationとかいう
Ai Suite 3を消すことで解決する。
普通に消そうとしても「The model does not support this application.」とか言われるので、公式にある適当なマザボのユーティリティからAI Suite 3 Cleanerを落としてきてAi Suite 3を消す。
モニタが片方しか映らない、モニタの映りが悪い、グラボが未検出
ZOTAC公式からドライバを落として入れる。
Ai Suite上でFan Xpertを使いたい(ASUS TUF GAMING Z790-PLUS D4)
ROG STRIX Z370-F GAMINGのツールから落としてインスコすれば使える。
ASUS TUF GAMING Z890-PLUS WIFIだと多分この方法は無理。
ASUS TUF GAMING Z890-PLUS WIFIでFan Xpertを使いたい
ASUS TUF GAMING Z890-PLUS WIFIのツールからArmoury Crateを落とし、Armoury Crateをインストール後、Armoury Crateの機能ライブラリからアシスタントをインストールすると使えるようになる。
Armoury Crateには過去に結構苦い思い出があったので入れるのを避けたかったが、他に方法はなさそうだ。ファンの細かい調整が不要ならBIOSからやってもいいかもしれない。
関連記事
ベンチスコアは複雑な結果になったので別記事、5070Tiは4070Tiより性能が悪い…?に譲る。
Automatic 1111よりいいらしいので使ってみる。
日本語表示が面倒だったので、途中から表示言語を英語に変えている。
確認環境
Env | Ver |
---|---|
ComfyUI | v0.3.38 |
導入方法
インストール
公式サイトからインストーラーをダウンロードして実行するだけ。
Cドライブにしか対応してないらしいが、モデルや出力先は変更可能なので、インストールパスはそのままでよい。
モデルパスの変更方法
- ComfyUIのインストール先を開く
標準はここ:%HOMEPATH%\AppData\Local\Programs\@comfyorgcomfyui-electron\resources\ComfyUI
extra_model_paths.yaml.example
をextra_model_paths.yaml
にリネームする- 以下のコメントアウトをコピペして適当に治す。
is_default: true
のコメントを外して有効化しておく#comfyui: # base_path: path/to/comfyui/ # # You can use is_default to mark that these folders should be listed first, and used as the default dirs for eg downloads # #is_default: true # checkpoints: models/checkpoints/ # clip: models/clip/ # clip_vision: models/clip_vision/ # configs: models/configs/ # controlnet: models/controlnet/ # diffusion_models: | # models/diffusion_models # models/unet # embeddings: models/embeddings/ # loras: models/loras/ # upscale_models: models/upscale_models/ # vae: models/vae/
出力先の変更方法
設定→サーバー設定の一番下にある「出力ディレクトリ」を設定する。
画像の保存ノードのファイル名プレフィックスをクリックし、Valueにフォルダ名/任意の文字列
をつけることでフォルダわけもできる。フォルダ名/
だけ指定してもうまくいかないので注意。
ClipSkipの設定(不明)
CLIP Set Last LayerノードをLoad Checkpointに接続することで実現できるらしい?
Hires.fixの設定
KSampler→Upscale Latent By→KSampler→VAEで繋ぐと同様のことができるらしい。
感想
起動が早い
1111は1分近くかかるがComfyは数秒で起動するため、ここはいいと思った。
保存先を柔軟に変更できる
1111では基本的に生成種別、日付別に保存されるため整理が手間である。
画像の生成品質を上げる方法がわからなかった
これはComfy UIを以下の構成にして生成したものだ。
一枚目はこういう絵柄だといえばまだありかもしれないが、二枚目は微妙だ。これはどうもHires.fix相当の機能が期待通りに動いていないのが理由に見えるが、恐らくそういった事柄を探求するモチベーションがないと、上手いこと使えないと思われる。
また上記のノード接続だと生成速度も速いとは言えず、これ以上要素を増やすとなると実用性は怪しいと感じた。
現状はまだ1111で十分
1111だとこのくらいのものがパッと出てくるため、個人的には今のところ1111でいいかなと思った。カリカリにチューニングすることで1111を超えてくる可能性は否定できないが、大抵のケースで設定値は固定であり、プログラマブルである必要性はアニメーションとかの分野になってくると思われるので、動画を作るならComfy、そうでなければ1111で十分な気がした。
マチアソビで白滝製麺が出していた半田そうめんの雰囲気だけ再現するレシピ。
材料
鳥チャーシューは入手困難で作るのも手間なので、鳴門に繋がるなるとで代用した。
材料 | 分量 |
---|---|
白滝製麵の半田そうめん | 1束 |
いりこそうめんつゆ | 適量 |
なると | 好きなだけ |
すだち | 適量 |
すじ青のり | 適量 |
卵 | 1個 |
水 | 1Lくらい |
調理方法
前準備
ゆで卵を一つ作っておき、すだちとなるともあらかじめ切っておく。
そうめん本体
- お鍋に水を入れてお湯を沸かす
- 半田そうめん一束を鍋に入れる
- 6分茹でる
- ざるに上げ冷水でよーく洗う。親の仇と思うくらい洗う。
- 目安としては、麺のぬめりがとれる程度もみ洗いする
- 夏場は水道がぬるくなりがちなので5-6月の時期にやると塩梅がよい
- 器に入れ、具とめんつゆをのせて完成
使った食材の参考写真
白滝製麺の半田そうめん。これは必須アイテムだ。
いりこだしのそうめんつゆは入手難易度が高いかもしれないが、丸天醤油のある兵庫県内では比較的手に入りやすいだろう、たぶん。
すだちは徳島県産しか見たことがないので、容易に徳島感を演出できる良アイテムだ。
すじ青のりはタコ焼き用に常備していたのがたまたま徳島県産だった。四万十か吉野川が多いと思うので、これも割と徳島産は入手しやすいだろう。
アオサは全く別物なので出来れば青のりを入手したいところだ。
マチアソビで出た半田そうめん
雰囲気で作ったので、翌々見なおしてみると、いうほど似てないなと思った。ただ味は似てると思う。
前々からこのブログの画像と文字の配置について悩んでいたが、結論が出たのでスタイルを変えることにした。
以前は以下のような方式だったのだが、補足説明と次の画像の説明の境界があいまいで判読しづらかった。
<画像の説明>
<画像>
<補足説明>
今回はこれを以下の形に刷新した。
<画像>
<画像の説明>
<補足説明>
この形式にしたことにより画像を区切り文章ができるため、どちらの画像に対する文章なのかが判別しやすくなった。
何故この形式にしたかは単純で、デイリーポータルZや海の見える駅 〜徒歩0分の景勝地〜など、この書式を採用しているサイトが多いからだ。これらのサイトでは加えて画像タイトルと判るような枠UIもついているが、文章構成が面倒になるので今のところそこまでするつもりはない。一応CSSで画像の上のパディングを広げることで、区切りを判別しやすくはしている。
変化としては上の表の通り。通常の画像は、画像個別にfigure > a > imgとなっており、文章はPタグで囲まれているため、Pタグの後ろの全figureに対しmargin-topを指定して対処している。
div.body-main p~figure {
margin-top: 1em;
}
adiaryの生成するHTMLは画像を挿入したときに前後にPタグを挿入する挙動をするため、手前に文章がなくても妙な空白が生まれてしまうが、現状は許容としている。
このPタグにはMarkdownで書いた画像の前後の行の文字列が入り、brを回避するように実装されているようで、修正が面倒なため、新ブログシステムを開発し、そっちに移行したときに対応したい気がしている。
あああ
<画像>
いいい
例えば、上記であれば以下のHTMLが生成される感じだ。
<p>あああ</p>
<figure><a href="画像パス"><img src="サムネ"></a></figure>
<p>いいい</p>
今回の対応では以下の形式にしているため、前後のPタグの中身は空白になる。要するにゴミが出ている。
<画像>
<画像の説明>
<補足説明>
<画像>
<画像の説明>
<補足説明>
...
今回の対応で対象となった記事は112、変更箇所となる文章行と画像行のセットは約1,089箇所にも及んだため、どこかの記事が置換ミスで壊れている可能性がある。ただまぁ読めなくはないと思う。
このブログはテキストファイルでデータを持っているため、置換作業はVSCodeの一括置換を主に使っていて、一応できる限り目検で怪しいところはチェックしている。たまにメタデータを破壊しそうになっていたり「以下」という文言が含まれていたり、二行連続で画像が続いているなどで整合性が取れなくなっている個所は極力て出直している。
ただどうしても万博記や、しょい地巡礼辺りは画像点数が余りにも多いので文章中に「以下」がないかを機械的に見て、上から下まで流し見した程度にとどまっているため、一部崩れている可能性は否定できない。
ひとまずこの作業をしている中でadiaryのコードをあれこれ見ていたところ、保守性に限界を感じてきたので、adiaryのデータフォーマットと互換性のあるブログシステムをPHP辺りで作りたい機運が高まった。気が向いたら作るかもしれない。
DBはテキストDBだと一括置換がしやすいとかは確かにあるのだが、システム保守やパフォーマンス面ではSQLiteが最強だと思っているので、恐らくテキストDBは捨てる気がする…。
パフォーマンス面についてはウチのように記事数が多いサイトだとSQLiteは1ファイルにデータが収まる関係でファイルI/Oの回数が減る分、オーバーヘッドが減ると考えているためだ。実際adiaryは時として重くなる。WordPressほどではないにせよ、看過していると今後の記事増加に耐えられない気もする。
RDBは今回のような一括置換に対しての保守性は悪いが、総合的なパフォーマンスはいいし、置換に関しては最悪WordPressにあるSearch Replace DBみたいなやつを作れば使い勝手が悪くとも出来なくはないと思うのと、基本的にまず発生しないはずなので考慮しない方向で行きたい。
例外設計についての個人的に思っていることを書き出してみる。整理できていないがいったん現状。TypeScriptのケースを意識して考えているが、根幹は例外スローのある言語ではどれも共通だと考えている。
例外とは何か?
本記事で扱う例外とはthrow new Error("ほげほげ");
のように、いわゆるスローされ、try-catchされるものを指して扱う。
例外を多用しない
例外は多用しないことが望ましく、原則として処理が続行不能になる場合を除き、使わないほうが良いと考えている。これはスローされた例外は可視化されづらく、適切にハンドリングされないケースがよくあるからだ。
例外は構造化されたプログラムを破壊する
構造されたプログラムとは順次・反復・分岐の基本構造を階層的に組み合わせたものであり、いわゆる上から下に読めばわかるもの、構造化プログラミングによって作られるものだ。上から下に流れるため非常にわかりやすい。
これに対して存在するのがgoto
を用いたプログラムだ。goto
を使うとコードの色んな場所に前後しながらジャンプすることが可能で、可読性を損ねてしまう。
そして例外は基本的にgoto
のような存在である。例外が起きると例外オブジェクトが投げられ、これはどこに行きつくか予想することが難しい。行きつく先がなければ最悪プログラムがクラッシュする恐れすらある。
例外は処理コストが重い
恐らく大抵の言語において例外をcatchする行為はコストが重い。これはJavaでは特に有名な話だと思うが、Java以外でもそうだと思う。例えばNode.jsでtry-catchで例外を処理するプログラムと、if-elseで処理するプログラムを書き、その実行速度を比較するとif-elseの方が早い。
以下はエラーハンドリングをifで行うプログラムと、try-catchで行うプログラムを作り、100万回走行させたときの処理時間だ。catchに入るケースでは処理速度が低下することが分かる。例外が投げられず、tryの中に納まる限りは低下しない。
処理 | 処理時間(ms) |
---|---|
If正常系 | 4,453 |
If異常系 | 4,204 |
try-catch正常系 | 4,341 |
try-catch異常系 | 7,883 |
これは例外が投げられる場合、最寄りのcatchポイントを探索するのに時間がかかるからではないかと考えている。
Node.js向け検証コード
前述の処理時間を出すのに使ったプログラム
// ==== 実行用共通部品
const execIf = (input) => {
if (input === 1) {
return true;
} else {
return false;
}
};
const execThrow = (input) => {
if (input === 1) {
return true;
} else {
throw new Error('ERR');
}
};
// ==== コールバック処理計測用関数
const getExecFuncElapsed = (cb) => {
const startAt = +new Date();
for (let i = 0; i < 1_000_000; i++) {
cb();
}
return +new Date() - startAt;
};
// ==== If/try-catch検証用、コールバック処理群
const execIfOk = () => {
const ret = execIf(1);
if (ret) {
console.log('OK=');
}
};
const execIfNg = () => {
const ret = execIf(0);
if (ret === false) {
console.log('ERR');
}
};
const execThrowOk = () => {
try {
execThrow(1);
console.log('OK=');
} catch (e) {
console.log('ERR');
}
};
const execThrowNg = () => {
try {
execThrow(0);
console.log('OK=');
} catch (e) {
console.log('ERR');
}
};
// ==== 計測処理
const elapsedIfOk = getExecFuncElapsed(execIfOk);
const elapsedIfNg = getExecFuncElapsed(execIfNg);
const elapsedThrowOk = getExecFuncElapsed(execThrowOk);
const elapsedThrowNg = getExecFuncElapsed(execThrowNg);
// ==== 結果出力
console.table({ elapsedIfOk, elapsedIfNg, elapsedThrowOk, elapsedThrowNg });
いつ例外を使うか?
基本的には大域脱出がしたいケースのみで使うべきだろう。最悪ハンドリングされずとも、基底階層でcatchされれば、それでよいケースで使うのが最も無難だと考える。
大域脱出とは要するにgoto
だ。多重ネストや深い高階関数から浅い階層に一気にすり抜けるときに有効だろう。逆に一階層とか、抜ける階層が浅いレベルでは使わないほうが良い。
例えば処理が続行不能になったケースでは例外をスローし、基底階層でcatchし、エラーログを吐く、クライアントに対してエラーメッセージを返すなどの処理があればよいと考える。
但し例外を使うときは極力カスタム例外を使ったほうがよいと考える。
フレームワークやライブラリの例外をどう扱うか?
例えばバリデーションエラーやHttpClient系の4xx, 5xx系の例外スローはラッパーを作り、例外をエラーオブジェクトに変換するのも一つだと考える。
HTTP GETを行うクライアント関数であれば以下のようなラッパーを作り、正常時は正常レスポンスを返し、異常時でかつ想定内であればエラーオブジェクトを返す、そして想定外の例外であればリスローする、といった処理をすることができる。
const httpGet = (url) => {
try {
return fetch(url);
} catch (e) {
if (e instanceof AbortError) {
return createHttpErrorObj(e);
} else {
throw e;
}
}
}
こうすることで呼び出し元は正常時であればHTTPリクエストをそのままステータスコードに応じて処理し、Abortされた場合はリトライ、完全に予期せぬ内容であれば例外を基底階層まで飛ばして処理を中断するといったこともできる。
リトライに規定回数失敗した場合は、この関数の呼び元でnew OutOfTimesHttpRetryError()
みたいな例外をスローするとよいだろう。
カスタム例外を使う
カスタム例外とは例外クラスを継承した例外クラスだ。
例えばC#ではExceptionのほかに、それを継承したSystemExceptionや、IndexOutOfRangeExceptionなど、様々なカスタム例外が存在する。
LaravelにもAuthorizationExceptionをはじめとし、多様なExceptionが存在する。
これらに限らず、大抵の言語やフレームワークには相応のカスタム例外が用意されているのが一般的で、業務システムやC2のプロダクトでも、例外をスローするケースではカスタム例外を作ることが望ましいと考える。
カスタム例外があると例外種別ごとにフィルタリングすることが可能になり、柔軟にハンドリングしやすく、ロギングの際にも例外種別を記録することで、後々の障害調査でも便利になるため有用だ。
例外を握りつぶさない
例外は時として握りつぶされることがある。そういう必要があるケースも少なからずあるだろう。しかし基本的に例外は握りつぶさないほうがよい。
例外は望ましくない現象が起きているはずで、本質的にハンドリングする必要がある。単に握りつぶしているだけでコメントやテストも書かれていなければ、もし例外が起きたとき、処理が正常に進むのかどうかコードから読み取ることが困難だ。
仮にテストがあったとしてもコードを読むときのコストが増えるので、基本的に握りつぶさないほうがよいだろう。
スローする場合は、例外クラスを用いる
JavaScript系では以下のようなエラーオブジェクトを作るケースもあると思うが、スローする場合は使わないほうが良い。
{
__type: 'HogeError',
message: 'fufagfuga',
payload: someObject
}
スローする場合はErrorクラスを継承したカスタムエラーをスローすべきだ。これはカスタムエラーにはスタックトレースなど、障害調査をするときなどに例外として標準的な情報が格納されているほか、instanceof
でフィルタしやすい、クラスは型情報を持つのでリファクタが容易、error.__type === 'HogeError'
は言語機能の再実装に近く標準的ではないからだ。テストフレームワークでも例外をキャッチするためのアサーションではErrorクラスの継承が必須となっているケースがあるため、TypeScriptでは型検査が上手く通らないケースがある。