2026年8月

2026年の一覧へ

8月31日

主任のお仕事とか。

長年アップグレードしてきたMacの重さがどうにも我慢できなくなったのでクリーンインストールする。

Subversionのリポジトリの場所を調べる。

svn info

これでURLがわかる。

あと、Slackのログイン先。

  • 研究室
  • 慶應
  • coi-next-quantum
  • QL
  • ESS
  • 川島研
  • SQAI Discussion
  • 分子シミュレーション研究創発センター
  • KEIO AIC

あとは秘密鍵だけ保存しておけば、あとは復活できるはず。

  • Macを再起動してCommand+Rを押しっぱなしにする。
  • 復旧アシスタントが起動するので「Macを消去」を選ぶ。
  • 何度やってもネットワークで失敗。有線にしたら成功
  • 「復旧」画面になるので「表示」で「すべてのデバイスを表示」
  • 左の「Machintosh HD」を選んで消去。
  • ディスクユーティリティを終了
  • macOS Tahoeをインストールを選ぶ。
  • インストール先にMachintosh HDを選ぶ

インストール終了後にやること

  • Chromeをインストール
  • デフォルトのブラウザをChromeに(これをしないと、この後の認証でSafariが開いて面倒なことになる)
  • Google にログイン
  • Gitのインストール(xcode–select installで入れる必要がある)
  • codexのインストール
    • nvmのインストール
    • nvm install –lts
    • nvm use –lts
    • npm install -g @openai/codex
    • codexを起動してログイン
  • Homebrewをインストール
  • github/dotfilesをクローン
    • ./install.sh を実行 (dotfilesがショートカットキーとして作られる)
    • ./install_tools.sh を実行 (astyle, isort, その他がインストールされる)
  • VSCodeのインストール
    • 起動してGitHubでSign inする。設定がSyncされる。
  • Subversionのインストール
    • brew install subversino
  • Subversionで管理されたファイルを一括clone
    • svn co path/to/url svn
  • 「システム設定」「キーボード」で、「キーのリピート速度」を早く、「リピート入力認識までの時間」を短くする。
  • Google 日本語入力をインストール
    • 再起動して、入力ソースとして「ひらがな(Google)」を追加。デフォルトを削除。
  • Pythonのインストール。
brew update
brew install pyenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init - zsh)"' >> ~/.zshrc
pyenv install 3.13
pyenv global 3.13
  • log用

    • brew install hugo
  • Chromeの慶応プロファイルを追加

  • Microsoft 365(https://m365.cloud.microsoft/apps/)から、KeioアカウントでログインしてOfficeをインストール。

  • PowerPointやWordの初回起動時にKeio アカウントでログイン

Slackのインストール

これであらかた必要なものが入ったかな。えらくスッキリした。Subversionで教育関連に必要なファイルがごそっと入るのが楽で良い。

さくらのパスワード変更。大丈夫なはずだけど念のため。

LaTeXのインストール。自分でいうのもなんだけど、これ便利だ・・・。

部屋の整理もした。書類整理に必要だったのでコクヨのケースファイルを発注。布テープも。

忙しいと、部屋の片付けとかしちゃうよね・・・

8月30日

横浜美術館のマリー・アントワネット展へ。10時開館に10時半についたら50分待ち!(実際には30分くらいで入れたが)。

8月29日

NOP

8月28日

大学院の口述試験。

その後会議。

その後会議。

その後会議。

8月27日

研究室ミーティング(TBA)

MN-Core SDKを簡単に使うためのDockerfileと使い方の記事書いた。

MN-Core SDKを使ってみる その1

続くかどうかは知らん。

8月26日

Jekyllセットアップ。

sudo apt update
sudo apt install -y git curl build-essential libssl-dev zlib1g-dev \
  libreadline-dev libyaml-dev libffi-dev libgdbm-dev libncurses5-dev \
  libdb-dev autoconf bison
cd
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

以下を.bashrcに追加。

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init - bash)"

Rubyを入れる。

rbenv install 3.2.9
rbenv global 3.2.9

Bundlerを入れる。

gem install bundler
rbenv rehash
bundle -v

ブログに必要なものをインストール。

cd github/kaityo256.github.io/
bundle install

プレビュー。

bundle exec jekyll serve --livereload

うーむ、ちょっと手間がかかりすぎている気がする。Hugoはもう少し楽だったような。

暑すぎる。

Notionのエントリーページ、ログイン状態にあることがわかりづらく、反射的に「ログイン」のつもりで「ログアウト」ボタンを押してしまうことが既に三回くらいある。大学として有料契約しているのに、「Notionを無料で始める」みたいな表示があったらログインしていないと判断しちゃうでしょ。これ、あまりUIとしてよくないと思う。

Slackの立て替え払い申請した。クレジットカードの明細は不要のはずなのに、なんか明細を待ってしまった。

さくらの立て替え払い申請もした。遅くなってしまった。来年から来たらすぐ出す。

TAの案内流した。昨年もちょうどこのあたりに流したようだ。

なんか予定をいろいろ間違えた気がする。

$ bash create_dev_ctr_macos.sh -A

Docker コンテナを起動。

docker exec --privileged -it c9f8dada416b bash

コンテナ内でMNISTを実行。

$ cd /opt/pfn/pfcomp/codegen/MLSDK/examples
$ ./exec_with_env.sh python3 mnist.py
(snip)
E0826 08:29:44.183156    19 mnlinker3.cc:106] Check `pfcpp::affinity_available()' failed!  in init at /opt/pfn/pfcomp/codegen/mnlinker/mnlinker3/mnlinker3.cc:106 with codegen_dir=/tmp/codegen_tmp_0000019/_compile_from_onnx.0/model.app.zst: Without setting appropriate affinity, MN-Core cannot perform best.

emit_codeは成功しているが、なんか失敗しているな。実機があるかどうかの判定がautoではうまくいかないようだ。

./exec_with_env.sh python3 mnist.py --device emu2

これで動いたが、極めて遅く、実時間での動作確認は難しい。PFVMのCPUバックエンドを使ってみる。

$ ./exec_with_env.sh python3 mnist.py --device pfvm:cpu
(snip)
<= compile_command end (3.913 sec)
=> send_to_others start
<= send_to_others end (0.000 sec)
<= DistributedMNCoreAppCompiler end (3.915 sec)
Correct: 9561 / 10000. Accuracy: 0.9561

動いた。PFVMとは、PyTorchで書かれた処理をONNXに変換、PFVMコンパイラが計算グラフを作り、それをPFVM Runtimeで実行する仕組み。

まず、create_dev_ctr.shをMacで実行するためには以下の修正が必要だった。

--- create_dev_ctr.sh	2026-07-27 20:53:51
+++ create_dev_ctr_macos.sh	2026-08-26 17:27:31
@@ -1,20 +1,20 @@
-#! /bin/bash
+#!/usr/bin/env bash
 set -eu -o pipefail

-MNCORE_REGEX='/dev/mnc.*'
-
 DOCKER="docker"
 IMAGE="mncore-sdk-full:0.6"
-SEMAPHORE_MOUNT="/opt/mncore_shared_semaphore:/var/tmp/mncore"
+DEFAULT_SEMAPHORE_DIR="${HOME}/.mncore_shared_semaphore"
+SEMAPHORE_MOUNT="${DEFAULT_SEMAPHORE_DIR}:/var/tmp/mncore"
+USE_DEFAULT_SEMAPHORE_MOUNT=1
 DOCKER_OPTS=()

 function usage() {
-    echo "$0 -- Launch docker container for MN-Core devenv" >&2
+    echo "$0 -- Launch docker container for MN-Core devenv on macOS" >&2
     echo "" >&2
     echo "$0 [-A] [-i IMAGE] [-s MOUNT] [-R RUNTIME_CLI] [-O DOCKER_OPTS] devices..." >&2
     echo "" >&2
     echo "Options:" >&2
-    echo "  -A              Mount all devices on the node to the container" >&2
+    echo "  -A              Use all MN-Core devices found on the host (emulator only on macOS)" >&2
     echo "  -i IMAGE[:TAG]  Use specified IMAGE (${IMAGE})" >&2
     echo "  -s MOUNT        Use specified MOUNT for sharing semaphore (${SEMAPHORE_MOUNT})" >&2
     echo "  -R RUNTIME_CLI  Container runtime CLI (${DOCKER})" >&2
@@ -27,59 +27,72 @@
 while getopts "Ai:s:R:O:h" opt; do
     case "${opt}" in
     A) USE_ALL=1;;
-    i) IMAGE=${OPTARG};;  # localhost/ prefix is required when run with -R podman, that is, the options would be -R podman -i localhost/mncore-sdk-full:0.6
-    s) SEMAPHORE_MOUNT=${OPTARG};;
+    i) IMAGE=${OPTARG};;
+    s)
+        SEMAPHORE_MOUNT=${OPTARG}
+        USE_DEFAULT_SEMAPHORE_MOUNT=0
+        ;;
     R) DOCKER=${OPTARG};;
-    O) DOCKER_OPTS+=(${OPTARG});;
-    h) usage
+    O) DOCKER_OPTS+=("${OPTARG}");;
+    h) usage;;
     esac
 done
 shift "$((OPTIND - 1))"

 DEVICES=()
 if [[ $# -ne 0 ]]; then
-    DEVICES=($@)
+    DEVICES=("$@")
 elif [[ ${USE_ALL} -ne 0 ]]; then
     echo "Enumerating devices" >&2
-    readarray -t DEVICES < <(find /dev -regex ${MNCORE_REGEX})
+    shopt -s nullglob
+    DEVICES=(/dev/mnc*)
+    shopt -u nullglob
     if [[ ${#DEVICES[@]} -eq 0 ]]; then
         echo "[WARN] No MN-Core device found. You can use emulator backend only" >&2
     fi
 else
     echo "E: No device list nor use-all flag (-A) specified." >&2
-    usage $0
+    usage
 fi

-# check if the image is already loaded to the system
-if ! ${DOCKER} image ls --format "{{.Repository}}:{{.Tag}}" | grep -q "^${IMAGE}$"; then
+if [[ ${USE_DEFAULT_SEMAPHORE_MOUNT} -ne 0 ]]; then
+    mkdir -p "${DEFAULT_SEMAPHORE_DIR}"
+fi
+
+# Check if the image is already loaded to the system.
+if ! "${DOCKER}" image ls --format "{{.Repository}}:{{.Tag}}" | grep -q "^${IMAGE}$"; then
     echo "E: Image ${IMAGE} is not found on the system."
     exit 1
 fi

+DOCKER_ARGS=(
+    run
+    --privileged
+    -d
+    -v "${SEMAPHORE_MOUNT}"
+)
+for dev in "${DEVICES[@]}"; do
+    DOCKER_ARGS+=("--device=${dev}")
+done
+DOCKER_ARGS+=("${DOCKER_OPTS[@]}" "${IMAGE}" sleep inf)
+
 echo "Starting container" >&2
-CTR_ID=$(${DOCKER} run \
-    --privileged \
-    -d \
-    -v ${SEMAPHORE_MOUNT} \
-    $(echo ${DEVICES[@]} | xargs -n1 printf " --device=%s") \
-    ${DOCKER_OPTS[@]} \
-    ${IMAGE} \
-    sleep inf)
-echo ${CTR_ID}
+CTR_ID=$("${DOCKER}" "${DOCKER_ARGS[@]}")
+echo "${CTR_ID}"

 echo "Setting up devices" >&2
-for dev in ${DEVICES[@]}; do
+for dev in "${DEVICES[@]}"; do
     echo "  ${dev}" >&2

-    if ! ${DOCKER} exec --privileged -it ${CTR_ID} gpfn3-smi config ${dev#/dev/} clock --core=750 --gddr6=15000; then
+    if ! "${DOCKER}" exec --privileged -it "${CTR_ID}" gpfn3-smi config "${dev#/dev/}" clock --core=750 --gddr6=15000; then
         echo "E: Failed to setup device ${dev}. Aborting" >&2
-        ${DOCKER} stop ${CTR_ID} >/dev/null
+        "${DOCKER}" stop "${CTR_ID}" >/dev/null
         exit 1
     fi

-    if ! ${DOCKER} exec --privileged -it ${CTR_ID} gpfn3-smi config ${dev#/dev/} mab; then
+    if ! "${DOCKER}" exec --privileged -it "${CTR_ID}" gpfn3-smi config "${dev#/dev/}" mab; then
         echo "E: Failed to setup device ${dev}. Aborting" >&2
-        ${DOCKER} stop ${CTR_ID} >/dev/null
+        "${DOCKER}" stop "${CTR_ID}" >/dev/null
         exit 1
     fi
 done

うーん、不必要にいろいろ修正してしまっているな。あとで最低限にしよう。

MN-Core Playgroundにも入ってみたが、今のところデモサイトという感じで、自分のコードをコンパイルしてどうの、という感じじゃないかな。

とりあえずCodexにhello.cを作ってもらった。

# cat hello.c
#include "mncl/device/mncore2.h"

NO_MANGLING void hello(void) {}

コンパイルする。

/opt/pfn/pfcomp/mncl/bin/mnclc hello.c -e hello -o hello.bin

-oをつけないとhello.binを吐いてくれないのでござるなぁ。

このSDKはUbuntuか。xxdを入れる。

apt update
apt-get install -y xxd

binを見る。

# xxd -l 64 hello.bin
00000000: 3000 0000 0000 0000 0000 0000 0000 0000  0...............
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000020: 0000 0000 0000 0000 0800 1000 0000 0800  ................
00000030: 0800 0000 0000 0000 0800 0000 0000 0000  ................

正しいのかわからん。CODEGEN_DUMP_VSM=1をつければVSMが出るっぽいが、適当なコードを書いても最適化で消されてしまう。

add.cを作ってみる。これが最小か?

#include "mncl/device/mncore2.h"

// z = x + y
//
// Each PE adds one f32x4x2 vector. Data is moved through the MN-Core 2
// hierarchy: DRAM -> L2BM -> L1BM -> PE, then back in reverse order.
NO_MANGLING void add(DRAM const f32* x,
                     DRAM const f32* y,
                     DRAM f32* z) {
  L2BM f32* l2bm_x = __builtin_l2bm_malloc(2048);
  L2BM f32* l2bm_y = __builtin_l2bm_malloc(2048);
  L2BM f32* l2bm_z = __builtin_l2bm_malloc(2048);

  L1BM f32* l1bm_x = __builtin_l1bm_malloc(256);
  L1BM f32* l1bm_y = __builtin_l1bm_malloc(256);
  L1BM f32* l1bm_z = __builtin_l1bm_malloc(256);

  // DRAM -> L2BM
  __builtin_dram_punicast_l2bm_0(x, l2bm_x, 128);
  __builtin_dram_punicast_l2bm_1(x + 4096, l2bm_x, 128);
  __builtin_dram_punicast_l2bm_0(y, l2bm_y, 128);
  __builtin_dram_punicast_l2bm_1(y + 4096, l2bm_y, 128);

  // L2BM -> L1BM
  for (int i = 0; i < 8; ++i) {
    __builtin_l2bm_distribute(l2bm_x + i * 512, l1bm_x + i * 64);
    __builtin_l2bm_distribute(l2bm_y + i * 512, l1bm_y + i * 64);
  }

  // L1BM -> PE
  f32x4x2 vx;
  f32x4x2 vy;
  __builtin_l1bm_distribute(l1bm_x, (void*)&vx);
  __builtin_l1bm_distribute(l1bm_y, (void*)&vy);

  // Exactly one vector addition.
  f32x4x2 vz = vx + vy;

  // PE -> L1BM -> L2BM
  __builtin_l1bm_gather((void*)&vz, l1bm_z);
  for (int i = 0; i < 8; ++i) {
    __builtin_l2bm_gather(l1bm_z + i * 64, l2bm_z + i * 512);
  }

  // L2BM -> DRAM
  __builtin_dram_punicast_upload_0(l2bm_z, z, 2048);
  __builtin_dram_punicast_upload_1(l2bm_z, z + 4096, 2048);
}
# CODEGEN_DUMP_VSM=1 /opt/pfn/pfcomp/mncl/bin/mnclc add.c -e add  2>&1 |grep fvadd
fvadd $aluf $lm72v -> $nowrite  # unknown-loc @ForwardRead3 ; unknown-loc @LMRead3

おそらく出来たっぽい。MNCoreの性質上、“Hello World"ができず、かつベクトル計算が最小だから、f32x4x2 が最小サンプルになる?

main.ccとadd.cはこうなるはず。

main.cc

#include <algorithm>
#include <cassert>
#include <cmath>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <vector>

#include "mncl/host/cl/cl.h"
#include "mncl/host/cl/constants.h"

std::vector<unsigned char> load_binary(const std::filesystem::path& path) {
  if (!std::filesystem::exists(path)) {
    throw std::runtime_error("kernel binary not found: " + path.string());
  }

  const auto size = std::filesystem::file_size(path);
  std::vector<unsigned char> data(size);
  std::ifstream input(path, std::ios::binary);
  if (!input.read(reinterpret_cast<char*>(data.data()), size)) {
    throw std::runtime_error("failed to read kernel binary: " + path.string());
  }
  return data;
}

int main() {
  constexpr size_t element_count = 4 * 4 * 16 * 8 * 2 * 4;
  constexpr size_t byte_size = element_count * sizeof(float);

  std::vector<float> x(element_count);
  std::vector<float> y(element_count);
  std::vector<float> z(element_count);
  for (size_t i = 0; i < element_count; ++i) {
    x[i] = static_cast<float>(i % 101) * 0.25f;
    y[i] = static_cast<float>(i % 97) * 0.5f;
  }

  cl_int status;
  cl_platform_id platform;
  status = clGetPlatformIDs(1, &platform, nullptr);
  assert(status == CL_SUCCESS);

  cl_device_id device;
  status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_EMU_MNCORE2, 1, &device,
                          nullptr);
  assert(status == CL_SUCCESS);

  cl_context context =
      clCreateContext(nullptr, 1, &device, nullptr, nullptr, &status);
  assert(status == CL_SUCCESS);
  cl_command_queue queue = clCreateCommandQueue(context, device, 0, &status);
  assert(status == CL_SUCCESS);

  auto binary = load_binary("add.bin");
  const size_t binary_size = binary.size();
  const unsigned char* binary_data = binary.data();
  cl_program program = clCreateProgramWithBinary(
      context, 1, &device, &binary_size, &binary_data, nullptr, &status);
  assert(status == CL_SUCCESS);
  cl_kernel kernel = clCreateKernel(program, "add", &status);
  assert(status == CL_SUCCESS);

  cl_mem d_x =
      clCreateBuffer(context, CL_MEM_READ_ONLY, byte_size, nullptr, &status);
  assert(status == CL_SUCCESS);
  cl_mem d_y =
      clCreateBuffer(context, CL_MEM_READ_ONLY, byte_size, nullptr, &status);
  assert(status == CL_SUCCESS);
  cl_mem d_z =
      clCreateBuffer(context, CL_MEM_WRITE_ONLY, byte_size, nullptr, &status);
  assert(status == CL_SUCCESS);

  status = clEnqueueWriteBuffer(queue, d_x, true, 0, byte_size, x.data(), 0,
                                nullptr, nullptr);
  assert(status == CL_SUCCESS);
  status = clEnqueueWriteBuffer(queue, d_y, true, 0, byte_size, y.data(), 0,
                                nullptr, nullptr);
  assert(status == CL_SUCCESS);

  status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &d_x);
  assert(status == CL_SUCCESS);
  status = clSetKernelArg(kernel, 1, sizeof(cl_mem), &d_y);
  assert(status == CL_SUCCESS);
  status = clSetKernelArg(kernel, 2, sizeof(cl_mem), &d_z);
  assert(status == CL_SUCCESS);

  cl_event event = nullptr;
  status = clEnqueueTask(queue, kernel, 0, nullptr, &event);
  assert(status == CL_SUCCESS);
  status = clEnqueueReadBuffer(queue, d_z, true, 0, byte_size, z.data(), 1,
                               &event, nullptr);
  assert(status == CL_SUCCESS);
  status = clFinish(queue);
  assert(status == CL_SUCCESS);

  float max_abs_error = 0.0f;
  for (size_t i = 0; i < element_count; ++i) {
    max_abs_error =
        std::max(max_abs_error, std::fabs(z[i] - (x[i] + y[i])));
  }

  std::cout << "x[1]=" << x[1] << ", y[1]=" << y[1]
            << ", z[1]=" << z[1] << '\n';
  std::cout << "max_abs_error=" << max_abs_error << '\n';

  clReleaseEvent(event);
  clReleaseMemObject(d_z);
  clReleaseMemObject(d_y);
  clReleaseMemObject(d_x);
  clReleaseKernel(kernel);
  clReleaseProgram(program);
  clReleaseCommandQueue(queue);
  clReleaseContext(context);

  if (max_abs_error != 0.0f) {
    std::cerr << "[FAIL] result mismatch\n";
    return 1;
  }
  std::cout << "[OK]\n";
  return 0;
}

add.c

#include "mncl/device/mncore2.h"

// z = x + y
//
// Each PE adds one f32x4x2 vector. Data is moved through the MN-Core 2
// hierarchy: DRAM -> L2BM -> L1BM -> PE, then back in reverse order.
NO_MANGLING void add(DRAM const f32* x,
                     DRAM const f32* y,
                     DRAM f32* z) {
  L2BM f32* l2bm_x = __builtin_l2bm_malloc(2048);
  L2BM f32* l2bm_y = __builtin_l2bm_malloc(2048);
  L2BM f32* l2bm_z = __builtin_l2bm_malloc(2048);

  L1BM f32* l1bm_x = __builtin_l1bm_malloc(256);
  L1BM f32* l1bm_y = __builtin_l1bm_malloc(256);
  L1BM f32* l1bm_z = __builtin_l1bm_malloc(256);

  // DRAM -> L2BM
  __builtin_dram_punicast_l2bm_0(x, l2bm_x, 128);
  __builtin_dram_punicast_l2bm_1(x + 4096, l2bm_x, 128);
  __builtin_dram_punicast_l2bm_0(y, l2bm_y, 128);
  __builtin_dram_punicast_l2bm_1(y + 4096, l2bm_y, 128);

  // L2BM -> L1BM
  for (int i = 0; i < 8; ++i) {
    __builtin_l2bm_distribute(l2bm_x + i * 512, l1bm_x + i * 64);
    __builtin_l2bm_distribute(l2bm_y + i * 512, l1bm_y + i * 64);
  }

  // L1BM -> PE
  f32x4x2 vx;
  f32x4x2 vy;
  __builtin_l1bm_distribute(l1bm_x, (void*)&vx);
  __builtin_l1bm_distribute(l1bm_y, (void*)&vy);

  // Exactly one vector addition.
  f32x4x2 vz = vx + vy;

  // PE -> L1BM -> L2BM
  __builtin_l1bm_gather((void*)&vz, l1bm_z);
  for (int i = 0; i < 8; ++i) {
    __builtin_l2bm_gather(l1bm_z + i * 64, l2bm_z + i * 512);
  }

  // L2BM -> DRAM
  __builtin_dram_punicast_upload_0(l2bm_z, z, 2048);
  __builtin_dram_punicast_upload_1(l2bm_z, z + 4096, 2048);
}
$ /opt/pfn/pfcomp/mncl/bin/mnclc add.c -e add -o add.bin
$ c++ -std=c++23 main.cc -o add_host $(pkg-config --cflags --libs mncl)
$ ./add_host
x[1]=0.25, y[1]=0.5, z[1]=0.75
max_abs_error=0
[OK]

できたっぽい。うーん、やっぱりOpenCL系の構文はしんどいなぁ・・・

いくつかハマりポイントがあって、MacのデフォルトのBashが古いのでreadarrayが使えない(Homebrewでbashを入れる必要がある)、Dockerイメージが要求する場所が読めないのでそこを修正する必要がある、mnclcのドキュメントがほとんどなく、何をどうしてよいかわからない、あたりか。

あとで「MNCore SDKを使ってみる」的な記事にまとめるか・・・

8月25日

講義の準備とか。プルリク用リポジトリを2026年にしたりとか。ついでにGitHub演習のリポジトリをAIに食わせて誤字脱字の修正を求めたら20件近く報告され、その全ての指摘が正しかった。うーむ。

内容についての修正点も求めたら死ぬほど出てきそうだが、ちょっと今対応できそうにないので後で。

学生の卒論中間発表(プレゼン技法発表会)のタイトル出揃った。自分で言うのもなんだけど、同じ研究室の研究とは思えない。

会議用のヘッドセットの調子が悪いので新しく注文。途中にミュートボタンとかがあるとよく誤動作をするのでボタンがないもの、そしてUSBの有線、さらに耳を柔らかく覆うもの、という条件で探すと、どうしてもゲーミングヘッドセットになってしまう。真面目な会議用なのに、ゲーミングほげほげとか書かれてしまうと買いづらい・・・ 注文したけど。

以前、食べようと思ってたお菓子に「OLに大人気!」とか書かれてて書いづらかったのを思い出す。なんというか、全く同じ製品を「ゲーミング用」と「ウェブ会議用」で名前を変えて出して欲しい。

8月24日

土日の日記をpushし忘れているっぽいな→マージした。

日本語のgit diffを見るのはこれが便利。

git diff --word-diff=color --word-diff-regex='.'

aliasに入れておいた方が良さそうだな。dcで登録した。

git config --global alias.dc "diff --word-diff=color --word-diff-regex=."

家のWindowsを再インストールして、正直かなりさっぱりした。大学のMacの動作が重くなっているので、これもさっぱりしたい。

Zennでこんな記事を見かけた。

或るログ研究者

各OSSに小規模なPRを出す

これを見て思い出す事件があった。ミネソタ大のLinux悪意パッチ事件だ。ミネソタ大学の研究グループがLinuxカーネルに偽パッチを送りつけて大学ごとBANされた事件。

調べてみたら、やはりこれは研究目的だったらしい。

Automated Defects Detection and Fix in Logging Statement

40件のプルリクを出し、そのうち25件がmergeされたと報告がある。

時系列は、

  • 2024年6月末にGitHubにlogresearchというアカウントが作られたらしい
  • 2027年7月に著名なOSSをフォークしている
  • 2024年7月2~3日にプルリクを出している
  • 2024年7月5日にはactivity をprivateに。
  • 2024年8月6日にLogFixerという論文をarXivに出す
  • 2025年4月22日にLogUpdaterと名前を変えた。

という流れ。

論文によると、149個のefective logging statementsを検出し、研究者2名が確認して91件を正しい修正と認定、そこからランダムに40件選んでPRを出したらしい。

ミネソタ大学のように「悪意あるパッチを人間が見抜けるか」という研究に比べれば「自動生成された正しいパッチを人間がどう評価するか」という研究である分、倫理的な問題は小さいとは思うが、これはPRに「自動生成されたパッチであること」「研究目的であること」「自動生成されたものではあるが、人間が目視確認していること」を記載すべきだろう。

なんか、AI時代、人間がAIのエサにされているという雰囲気を強く感じる。

集中力が無い。学生さんの論文の図を作ったり、アナウンスをしたりした。

8月23日

ゲームを公開。

Stardust Sweeper

PCを再インストールしたので、ブログの動作確認のためのJekyllの環境構築のためにRubyとBundlerが必要。

rbenvとbundlerのインストール。

sudo apt update
sudo apt install -y \
  git curl build-essential \
  libssl-dev libreadline-dev zlib1g-dev \
  libyaml-dev libffi-dev
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init - bash)"' >> ~/.bashrc
source ~/.bashrc
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 3.4.10
rbenv global 3.4.10

うげ、いちいちビルドするのか・・・

なんか、ここはHugoだし、ブログはJekyllだしで、なんか面倒だなぁ。

8月22日

もう一つゲームを作った。

uvのインストール。

curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env

8月21日

データ解析スクリプトを書いた。人間の目では簡単に判定できるものが、機械的にやろうとすると難しい。

8月20日

研究室ミーティング。

  • 将棋のNNUEの話。「高速に差分計算可能なニューラルネットワーク型将棋評価関数」というアピール文書になっている。
  • Designing molecular RNA switches with Restricted Boltzmann machines, Jorge Fernandez-de-Cossio-Diaz et al. Nature Communications 16, 11223 (2025)

前者のNNUEの話は面白かったが、まだ実装を理解しきれていない。後者の話はRBMにより実際にRNAスイッチ(の機能の一部)を実装してみせた、というもの。数値シミュレーションだけでなく、実際にその配列で現物を作り、実験により評価したというもの。2025年に単純RBMでNature出せるだな。実験ありきだとは思うけれど。

Windowsを再インストール。なんかデフォルトインストールされてたウィルスバスターがアンインストールできず、トレンドマイクロから専用ツールを使ってアンインストールした。なんだかなぁ。

WSLをインストール。

wsl --install

ssh keychainの設定。

nvmのインストール、からのcodexインスト-ル。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash
nvm install --lts
nvm use --lts
npm install -g @openai/codex

8月19日

一日会議。

8月18日

研究室サーバの電源ON。まずはファイルサーバから。

ファイルサーバが上がったのを確認してログインノード(NISサーバ)を立ち上げ、ログインノードが上がったあたりで計算ノード(NISクライアント)を立ち上げた。

まずはNISの確認。

またポート番号が変わっている。ポートを昔開けた861に固定。/etc/sysconfig/network に以下を追記。

YPSERV_ARGS="-p 861"

その後再起動。

sudo systemctl restart ypserv
$ rpcinfo -p localhost
   program vers proto   port  service
    100000    4   tcp    111  portmapper
    100000    3   tcp    111  portmapper
    100000    2   tcp    111  portmapper
    100000    4   udp    111  portmapper
    100000    3   udp    111  portmapper
    100000    2   udp    111  portmapper
    100004    2   udp    861  ypserv
    100004    1   udp    861  ypserv
    100004    2   tcp    861  ypserv
    100004    1   tcp    861  ypserv

861になった。これで計算サーバにもNISが通った。

なぜかyagami03が死んでいる。yagami01,02だけ復活させる。

sudo scontrol update NodeName=yagami01.appi.keio.ac.jp State=RESUME
sudo scontrol update NodeName=yagami02.appi.keio.ac.jp State=RESUME
$ sinfo -N -l
Tue Aug 18 23:45:24 2026
NODELIST                  NODES PARTITION       STATE CPUS    S:C:T MEMORY TMP_DISK WEIGHT AVAIL_FE REASON
yagami01.appi.keio.ac.jp      1     main*        idle 20     20:1:1      1        0      1   (null) none
yagami02.appi.keio.ac.jp      1     main*        idle 20     20:1:1      1        0      1   (null) none
yagami03.appi.keio.ac.jp      1     main*    drained* 20     20:1:1      1        0      1   (null) planned_power_outage

yagami01,02だけ復活。03は明日確認。

RBM論文、arxivでリプレースされたんだけど、なぜかPDFが古い。

arXiv:2509.04899

メタデータも、HTML (experimental)も更新されているが、PDFとTeX Sourceが古い。なんか変にキャッシュされてるのか?しばらく待って直ってなかったら再投稿?

昔作ったRubyスクリプトを修正しようとしたら、Rubocopがうるさいこと。特に、「関数の引数は3文字以上」という制約が厳しい。これがRuby独自なのか、いくつかの言語について調べてみた。

  • Python PEP8 lowercaseであることだけ。最低文字数の定めなし。
  • C++ — Google C++ Style Guide snake_caseとだけ定められている。
  • Java — Google Java Style Guide 引数は lowerCamelCaseであること、パブリックな関数は一文字は避けることが書いてある。
  • JavaScript — Google JavaScript Style Guide lowerCamelCaseであること、パブリックな関数は一文字は避けることが書いてある。一方、「スコープが10行以下で、exported API の引数でなければ、1文字変数名でもよい」と踏み込んだ記述がある。
  • Effective Go 探した範囲では、関数の引数に関する規定がない。公式のサンプルに一文字の引数を多数利用している。Go Wiki では、逆にlineCountよりc、sliceIndexよりiを使えと、短い名前を推奨している。
  • Microsoft C# camelCaseであることが求められているが、最低文字数は定められていない。
  • Swift — Swift API Design Guidelines 引数についての明確な規定はなさそう。
  • Community Ruby Style Guide おそらく規定はない。

要するに、Rubcopが独自に厳しい。

さらに調べてみたが、RuboCop 0.53でNaming/UncommunicativeMethodArgNameが導入され、その時に既にMinNameLength: 3が指定されていた。これがNaming/MethodParameterNameに変更され、今にいたる。

直接の議論は[Fix #3666] Adds Uncommunicative MethodArg & BlockParam Naming copsかなぁ。要するに洗い出しに使って、必要ならAllowedNamesに追加していってね、という感じらしい。うーん。

LSW理論の分布関数を出力するスクリプトを整理して公開。

LSW Distribution

以前書いたノートの分布関数、3倍だけ計算が間違えている。レビュー論文を参考にしたはずなんだけどなぁ。いまBaldanのレビュー論文を読み直してみたけど、そこには書いてなかった。いずれにせよ、もういちどノートを整理してブログかどこかで公開したい。

PCの電源が壊れたのと、マウスの調子が悪いので注文。

8月17日

昨日のディズニーが足に来ている。

RBM論文を再投稿した。arxivのリプレースもした。

8月16日

娘とディズニーランドへ。

スプラッシュマウンテンが思ったよりスプラッシュしてずぶぬれに。

9時から18時30まで、11アトラクションを制覇。昨日の時点で空きがなかったレストランにもキャンセルがでて、12:20にイーストサイドカフェでご飯を食べることができた。非常に順調。

去年のディズニーシーが死ぬほど暑かったので、暑さ対策をしてきたのだが、終始曇り or 小雨で、かえって過ごしやすかった。ただ、一番の目的だったプーさんのハニーハントが運休だったのが残念。あと、ホーンテッドマンションも運休だった。

8月15日

停電のため、計算サーバを落とす。slurmでDRAIN状態にしてからそれぞれshutdown。

sudo scontrol update NodeName=yagami01.appi.keio.ac.jp State=DRAIN Reason="planned_power_outage"
sudo scontrol update NodeName=yagami02.appi.keio.ac.jp State=DRAIN Reason="planned_power_outage"
sudo scontrol update NodeName=yagami03.appi.keio.ac.jp State=DRAIN Reason="planned_power_outage"
ssh yagami01
sudo shutdown -h now
ssh yagami02
sudo shutdown -h now
ssh yagami03
sudo shutdown -h now

ファイルサーバのシャットダウン。まずはumount。

sudo umount /home
umount.nfs4: /home: device is busy

おっと。誰かが使ってる。

$ sudo fuser -vm /home
                     USER        PID ACCESS COMMAND
/home:               root     kernel mount /home
                     user1  583544 F.ce. code-f6cfa2ea24
                     user2  1117848 F.ce. code-fcf604774b

ログインしていないが、プロセスが残っているな。

sudo pkill -KILL -u user1
sudo pkill -KILL -u user2
sudo umout /home
ssh hiyoshi
sudo shutdown -h now

最後にログインノードをshutdownしておしまい。

いいかげんNIS+NFSをなんとかしなければと思いつつ、LDAPに踏み出せない自分がいる。

8月14日

NOP

「慣れたら一日でパズルゲームくらいリリースできるんじゃね?」と、昨日と同じ手順で作ってみたが、アクションパズルにしたらルール解釈がAIと合わない、キャラクターがうまく動かない、スプライトをうまく切り出せない、とトラブルが続出してうまく作れなかった。うーむ、向き不向きがあるな。

キャラクタースプライトでいえば、複数マスにまたがる処理が入るとうまく生成できない。ルールが複雑だとかなり詰めてもうまく伝わらない。うーむ。

8月13日

HodokuをItch.ioでリリースした。

Hodoku

今調べたら、

  • ChatGPTでプロジェクトの「壁打ち」を開始したのが8月11日の23:44
  • 「壁打ち」のうち、パズルゲーム作成に関して終わったのが Aug 12 00:20:45。ここでパズルゲーム生成コードの生成に入った。
  • 次の日に「ゲームUI」の壁打ちをしてゲーム実装に入る。
  • HodokuをGitHub Pagesでリリースしたのが8月12日の深夜
  • そして、Itch.ioでリリースしたのが8月13日の夜

ということで、ほぼ丸2日でゲームの使用策定からリリースまでできたわけだ。しかもこれにかかりっきりというわけではなく、壁打ちは布団で寝る前にスマホでポチポチだし、実装は家事の合間にエンターキーを押すだけ(たまに修正指示したけど)だし、あまり手間がかかっていない。

改めてすごい時代だな・・・

8月12日

「Hodoku」というゲームを作った。

Hodoku

Gitのログを見ると、Initial commitが

Date: Wed Aug 12 00:20:45 2026 +0900

となっている。その前の日にChatGPTと壁打ちして仕様を作成し、完成したPLANS.md、PLANS_maker.md、PLANS_game.mdをコミットしたのが11日深夜。

そのままパズルの問題作成を行い、次の日にゲーム作成を行った。問題作成が重かったのでMPIで自明並列にして探索させた。

作曲も自分でやろうと思ったが、ちょっと時間的に苦しかったのでSuno Proプランで作った。

中学生の頃からたくさんゲームを作ってきたが、ゲームを作るのは久しぶり。おそらくFlashで昔作ったゲームをリメイクしたのが最後だろう。

ゲームの絵や音楽に関しては完全に「ポン出し」だが、ゲーム本体はそうもいかず、実装させては確認、テストプレイして修正を指示を繰り返した。家事の合間に実装させ、指示待ちになってたら修正して・・・という感じ。べったり張り付いてはなかったが、それでもまぁまぁ時間はかかった。

ゲームプログラミングに関しては完全にAIに任せた。ゲームエンジンとしてGodotを採用したが、Godot scriptに関しては完全にノータッチ。昔、ゲームエンジンから自作していた(エンジンを作っていたのは僕ではなく友人だが)頃に比べると隔世の感がある。

果たしてこれ、「僕がゲームを作った」と言ってよいのか微妙だが、それでも漠然と頭に浮かぶアイディアがこうして形になるのは気持ちが良い。

ただ、ゲームを作ったのはほとんどAIなので、その製作体験記もAIが書くべきであろうと、ブログはAIに書かせた。

AIを使ってパズルゲームHodokuを作った

8月11日

塾の夏期講習の送り迎え x 2。それぞれ1時間半あったので、その間に査読x2を済ませた。

粗大ごみもたくさん捨てた。だいぶ家がきれいになった。

ブログの改良。まず、検索をつけた。記事のタイトルについてはインクリメンタルサーチで即時表示、本文はGoogleに投げる。「こんなの書いた気がするんだけどなぁ」と探すことが多かったのでとても便利に。しかし380記事もあるのか。

また、デフォルトのページネーションがいまいちだったので、数字で指定できる形に修正。

8月10日

購入したケルヒャーで外壁を掃除。すごい勢いで苔汚れが取れる。ゴシゴシ不要。素晴らしい。ただ疲れた。

家を少しずつ片付けている。これまで子供が二人連続で中学受験だったので、とても家の片づけまで手がまわらなかった。

査読をなんとかしなければならない。最近多い。知り合いがエディタになったかなぁ。

学生さんのジョブ、たぶん走り切ってるのになぜかタイムアウトする。ただ、データはできているので、それを解析スクリプトを走らせてみる。3021888。

8月9日

ケルヒャーを購入。

娘とホラーゲームを作った。まずChatGPTと壁打ち。やりたいことを伝えて最終的にPLANS.mdを作ることを目的とするというと、向こうがおおむね三択で仕様を提案してきて、それについてどれにするか選ぶだけ。20問くらいやりとりしたら、最終的に向こうがPLANS.mdを生成してくる。

それをCodexで読み込ませる。Phase 1から23まであり、少しずつ作りながらテスト。気になったところを修正しながら作っていく。なんだかんだで半日くらいかかったが、一通りプレイ可能な一人称視点3Dホラーゲームができてしまった。すごい時代だな。

ただ、敵の行動ルーチンがアホですぐにひっかかってしまうのを修正したり、部屋のレイアウトが甘かったり、生成された効果音がダメダメだったりするので、そのあたりは手動で修正する必要がある。でも、これもすぐに全部できるようになるんだろうな。

ちなみにGodot 4で作った。ある程度修正したら公開しよう。

8月8日

度が合わなくなってきた息子の眼鏡を購入。なんか保証期間内ということで無料。ラッキー。

子供の送り迎えをしたり、棚を移動して掃除したり。

なんかSNSで学歴について話題になってて、うっかり反応してしまったのだが、そしたら「学歴は大事だ」みたいなレスがついた。見てみると、「学歴」で検索しては「学歴は大事」「国立理系は勝ち組」とレスしてまわるだけのアカウントらしい。文章から、おそらくAIではなく人間。なんというか、呆れを通り越して哀れだなぁ。

codexを入れる。

nvm install --lts
nvm use --lts
npm install -g @openai/codex

実行したらbubblewrapがないと怒られた。

sudo apt install -y bubblewrap

というわけで、ついにこの日記のブログ化を実施。このMarkdownファイルを正本として、PythonでばらしてHugoでビルドする形式にした。懸案だったRSSにも対応(この日記の読者がどれくらいいるかわからないが・・・)。

なんかこういう「やらなきゃなぁ。でも面倒だなぁ」ということがすべてサクサクできるようになったのはAIのおかげだ。しかし、それだけに恐ろしい。子供たちの世代はどうなるんだろう。

8月7日

会議。

「一週間でなれる!スパコンプログラマ」の英語化を完了した。

Become an HPC Programmer in Seven Days!

かなりの作業量があり、AIがなければやろうとは思わなかったな。

DEV Communityにも投稿しておいた。

学生さんのジョブのスパコンへの代理投入、ミスってた。サイズを大きくしたのに、git pullに失敗していることに気づかずに投げてしまった。ちゃんとmergeして投げ直した。

MN-CoreのSDKをなんとかしようとしたが、全く手をつけられていない。こちらから「こういうのが欲しい」と言ったのに申し訳ない。

また査読が来た。なんか最近多いな。

明日から夏休みか・・・

8月6日

そうか、AIを使うとこれまで面倒だったことが全部できるんだな。QiitaやZennの記事をブログに引っ張ってきたが、そのリンクがQiita、Zennのままになっているのを直さなきゃなぁ、と思っていた。そんなの、Codexに頼んで昼飯食ってれば修正できるんだな。頼んでおこう。

・・・さて、出来たかな。リストアップされたリンク先を確認しよう。

根拠:Zenn側slugにtypoがあるが本文「その1」と対応記事内容が一致

やかましいわ。

さらに、Qiitaから持ってくる時に、僕がSlugミスをして、「ParaViewでVTKレガシーフォーマットを使う その2」を、なぜか「ParaViewでVTKレガシーフォーマットを使う その1」として持ってきてしまった。その修正もCodexにやってもらった。また、URLが生ではってある箇所も見つけたので、全てなおしてもらった。

548件の置換が完了しました。次に、残存リンクが「対応なし」「置換不要」だけであること、差分の範囲、ビルド結果 を確認します。

548件か。手作業でやったら、スクリプトを駆使しても面倒だったな。

研究室ミーティング。

  • F. Battiston, V. Nicosia, V. Latora, and M. San Miguel, Layered social influence promotes multiculturality in the Axelrod model, Scientific Reports, vol. 7, 1809, (2017).
  • D. Gessert, M. Weigel, and W. Janke, Frustrated Ising model on the honeycomb lattice: Metastability and universality, Physical Review B, vol. 113, 104436, (2026).

どちらも興味深かったのだけれど、後者の論文見た時に「W. Jankeってまだ論文書いてるんだ!」と驚いてしまった。調べたらまだ70歳。W. Jankeは僕が博士課程の学生の頃にはもう有名な研究者だったので、もっと年上だと思ってた。

ChatGPTに聞いてみた。僕が参加した夏の学校は「Computer Simulations of Surfaces and Interfaces」であり、NATO Advanced Study Institute(NATO ASI)/Euroconferenceとして開催。日時は2002年9月9日~20日、場所はブルガリア・アルベナ(Albena)。

この夏の学校の講義録が出版されている。

Computer Simulations of Surfaces and Interfaces

講義録には、K. Binder、D. C. Rapaport、W. Janke、N. B. Wilding、D. P. Landau、M. A. Novotnyなど有名人が並ぶ。やはりW. Jankeはこの夏の学校の講師だったようだ。いや、W. Jankeにはこの夏の学校で会った気がしていたのだが、当時の2002年の日記に記録がないため、2014年の日記に「会ってなかったっぽい」と書いてある。

ただ、D. P. Landauがブルガリアにいた記憶はないなぁ。

ついでに以下の日記の記述について調べてもらった。

Balchikへ。 Balchikというのは植物園のようなところだが、もともとは 庭付きのお城。 第一次大戦後にブルガリアがルーマニアに領土を奪われたとき、 ルーマニアの女王マリアが来てこの場所を気に入り、城を建てた。 ある時マリアの子供が海でおぼれたとき、トルコ人の漁師ハサンに 助けられた。彼はハンサムでかっこよく、 女王は恋に落ちてしまう。ところが実はハサンは海賊で・・・ というおとぎ話のようなバックストーリーがこの地にはある。

ChatGPTによると、溺れたのは女王マリアの娘、イレアナ王女(Princess Ileana, 1909–1991)、漁師ではなく商人で、海賊という情報は見つからなかったらしい。この伝説は、例えば以下のサイトで見られる。

The Palace of the Romanian Queen

うん、こんなところだった。懐かしい。

8月5日

スパコン一週間、パワポの英訳をしようとしてChatGPTに聞いたら、「まず対訳表を作ると良いですよ」と言われたので、対訳表を作るようにPLANS.mdを更新してcodexに投げる。するとPythonのpython-pptxパッケージを使って日本語を取得、対訳表をCSVで作って僕がそれを確認、OKを出したらPowerPointが翻訳された。すげぇ。

なんかGitHubにDependabotというボットからプルリクエストが来ている。最初、SPAMかと思ったが、GitHubの機能らしい。

いろいろ調べた(というかCodexに聞いた)が、マージできる奴とできない奴があるので、マージできる奴はマージ、できない奴はbotに無視しろとコメントすることに。っていうか、Codexにghコマンドの権限渡して「はいはい」って言うだけ。

Botに無視しろといったPRはこれ。

AIに作らせたGitHub Actionに、GitHubのbotがプルリクを作り、それをAIにレビューさせてAIが「ignore this major version」と(僕を通じて)返事をして、botが「OK, I won’t notify you about version 7.x.x again, unless you re-open this PR.」と返事をしてきた。

もう近未来とかそういう雰囲気を超えている。

っていうか、Codexが.github/dependabot.ymlを作成しているな。これでbotが反応したのか。

version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly

  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly

論文のイントロ書き直した。全体をチェックしてから共著者に送った。もうすぐ再投稿できるはず。

学生さんのジョブも投げた。

理事の仕事までは手をつけられなかった・・・

8月4日

物性研で会議。

三澤さんのリポジトリ見ててCFFファイルというものを知った。これはCitation File Formatの略で、GitHubのリポジトリにCITATION.cffがあると、右のメニューに引用方法が表示される。なるほど。

さっそくいくつか論文に関連づいているリポジトリにCFFファイルを追加してみた。

夜、ふと思い立ってAIに「一週間でなれる!スパコンプログラマ」の英訳をさせてみた。ついでに、英語と日本語を分けるためのディレクトリ構造と、Pandocではなく別の方法による管理を提案させたら、Astro Starlightを提案されたのでそれでやらせてみた。

最初は「量があるので、ローカル翻訳を試して良いですか?」と聞いてきたので、「いいよ」といったら、Pythonの翻訳ライブラリを試してから「やっぱ使えないのでマルチエージェント立ち上げていいですか?」って言ってきて、「いいよ」といったら、「それでは1,2章、3,4章、5-7章の翻訳をそれぞれのエージェントに任せて、私は全体の統括をします」とか言い出して、なんかもう、なんだろうこの近未来感。

これまでCodexは「部下」のつもりだったんだけど、なんか、その部下にさらに部下がいるという。自分が「課長」だと思ってたら、もう「部長」になってたような感じ。すごいなぁ。

で、放置して晩ごはん食べて戻ってきたら翻訳が出来ている、と。すごいなぁ(語彙力)。

8月3日

以前、「Xでポストがバズってましたね」って言われて「え?」と聞いてしまった。自分で言うのもなんだけど、わりとバズっているので、慣れているというか、「バズっていたポスト」がどれかがわからなくなる。

とりあえずバズるの定義を万バズとし、万バズの定義を「いいねが1万」として、「min_faves:10000 from:username」で自分のバズったポストを調べてみた。

  • 2026/7/27
  • 2026/6/21
  • 2026/5/17
  • 2026/2/10
  • 2026/1/18
  • 2026/1/4
  • 2026/1/1
  • 2025/12/6
  • 2025/11/21
  • 2025/11/19
  • 2025/11/12
  • 2025/10/19
  • 2025/7/22
  • 2025/5/10
  • 2025/3/16
  • 2025/2/19
  • 2025/2/9
  • 2025/1/25

2025年1月から2026年7月まで、19ヶ月で18回ですか。連続したり間があいたりはしているけど、概ね1ヶ月に1度という感じ。まぁ、これなら「ポストがバズってましたね」と言われて「どれ?」と聞き返してもギリ不遜ではなさそうですね。

しかし、Xの「For You」は駄目だ。どんなに「浄化」しても、すぐに喧嘩しているか「ざまぁ」系か、「困ったことを言っているアカデミアの人」のポストが流れてくる。これは、結局僕がそういうポストをクリックしてしまう、ということなんだろう。ようするにXのFor Youはカイジの「偽善の壁」であり、自身のダメさの鏡なんだ。

そういえばXの広告が鬱陶しくて言語設定を英語にしているので「For You」になってるんだけど、なんかこの設定、もうあまり意味がなくなってる気がするな。

RuffがMarkdownの整形をしようとして「Preview機能だから使うなら指定しろ」と警告を出してくる。ChatGPTに聞いたら「Prettier使えば?」とのことなので、VSCodeに拡張機能Prettierをインストール。以下の設定を追加。

  "[markdown]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true,
  }

おお、便利だ。OLで

1. hoge
1. hoge
1. hoge
1. hoge

とある時に、

1. hoge
2. hoge
3. hoge
4. hoge

としてフォーマットすると連番に、逆に1. 1.の状態でフォーマットすると全て1. 1.になる。余計な改行も減る。

RBM論文を大幅に書き直した。あとは関連論文を読むのとIntroductionを修正するだけ(それが一番大変という話もある)。

8月2日

実家へ。

8月1日

クローゼット組み立てたりした。

日本物理学会・巻頭言 LaTeX テンプレートを整理して公開した。