Makefileで並列処理 / jオプション その2 エラー回避策

並列処理するため”make all -j12″を実行した場合に初回エラーになる不具合の解決策が見つかりました。

エラー内容を確認すると、オブジェクトファイルが揃わないうちにリンクしていることが判明しました。そこでMakefile内の順番を変えて、必ずコンパイルが全て終わってからリンクするようにしました。

これで確実に並列処理できるようになりました。

# コンパイル後リンク ← この部分を前にもってきた
.PHONY: all
all: $(TARGET)

# oファイルから実行ファイルとappファイル作成
$(TARGET): $(OBJS)
	$(COMPILER) -o $(TARGETDIR)/$@ $(OBJS) $(LIBRARY0) $(LDFLAGS) $(LIBRARY)
	mkdir -p $(TARGET).app/Contents/MacOS
	mkdir -p $(TARGET).app/Contents/Resources
	cp $(TARGETDIR)/$(TARGET) $(TARGET).app/Contents/MacOS/$(TARGET)
	cp ./images/$(TARGET).icns $(TARGET).app/Contents/Resources
	echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $(TARGET).app/Contents/Info.plist
	echo "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" >> $(TARGET).app/Contents/Info.plist
	echo "<plist version=\"1.0\">" >> $(TARGET).app/Contents/Info.plist
	echo "<dict>" >> $(TARGET).app/Contents/Info.plist
	echo "  <key>CFBundleExecutable</key>" >> $(TARGET).app/Contents/Info.plist
	echo "  <string>$(TARGET)</string>" >> $(TARGET).app/Contents/Info.plist
	echo "  <key>CFBundleIconFile</key>" >> $(TARGET).app/Contents/Info.plist
	echo "  <string>$(TARGET).icns</string>" >> $(TARGET).app/Contents/Info.plist
	echo "  <key>CFBundleIdentifier</key>" >> $(TARGET).app/Contents/Info.plist
	echo "  <string>com.yourcompany.$(TARGET)</string>" >> $(TARGET).app/Contents/Info.plist
	echo "  <key>CFBundleName</key>" >> $(TARGET).app/Contents/Info.plist
	echo "  <string>$(TARGET)</string>" >> $(TARGET).app/Contents/Info.plist
	echo "  <key>CFBundleVersion</key>" >> $(TARGET).app/Contents/Info.plist
	echo "  <string>1.0</string>" >> $(TARGET).app/Contents/Info.plist
	echo "</dict>" >> $(TARGET).app/Contents/Info.plist
	echo "</plist>" >> $(TARGET).app/Contents/Info.plist

# 全ファイル削除
.PHONY: clean
clean:
	rm -rf $(OBJS) $(TARGETDIR)/$(TARGET) $(TARGET).app

Makefileで並列処理 / jオプション その1

CPUのコアをフルに使ってビルドする場合はjオプションを追加します。諸説ありますが、基本的にはコア数を付けてビルドします。

# M2 Pro Mac miniは12コア
make all -j12

Makefileはそのまま使えます。今のところ最初のmakeコマンドでは失敗しますが、2回目で正常にビルドできます。

オブジェクトファイルの作成を並列処理できるので、その工程は大体1/cppファイル数(12以下)の処理時間に短縮できます。今回は8ファイルなので約1/8です。かなりの高速化になります。ただしMakefileを複数用いる場合は何らかの工夫が必要になるようです。

比較的簡単なプログラムであればものの数秒でビルドできてしまいます。ここまで高速化できると、C++を扱うホビープログラマにとってはM1で十分です。

ただXcodeでSwiftのプロジェクトをビルドするとそれなりに時間がかかるため、M2 Proでもまだ足りないですね。

今は1回目に必ずビルド失敗する状況ですから、最初からmake allコマンドでシングルコア・ビルドしていれば良いわけでちょっと微妙な改良ではあります。ビルドに数分かかるような大きめのプログラムでしたら導入の価値ありです。

M2 Pro Mac miniをクリーンインストール 2024年11月

昨年2023年8月に購入したMac mini 整備品の内部ストレージ1TBが一杯になったのでクリーンインストールしました。外部ストレージ1TBも余裕がなく2TBにサイズアップしました。

折しも発売になったM4 Pro Mac mini 2TBへの買い替えも考えましたが、さすがに思いとどまりました。

手順

1.起動ディスクの作成
Mac miniのデータを外部SSD 1TBに移行し、起動ディスクにした。移行前にmacOS SequoiaをmacOSユーティリティを使ってインストールしている(ユーティリティ画面は電源ボタン長押しで出現)。

2.MacにOSインストール
・Mac miniのデータを消去し、macOS Sonomaをインストール。Sequoia 15.1.1でクラッシュしたためSonomaのまま。
・起動ディスクをストレージとして接続した状態でMac miniを起動する。

3.前環境の移行
・用意しておいたHomebrewのBrewfileやPyPIのrequirements.txtを起動ディスクのホームディレクトリからMac miniホームディレクトリへコピーし、下記記事に従って導入する。
・.bash_profileや.vscodeディレクトリをコピーする。
・シェルを常用しているものに変更する(Zsh → Bash)。
・デスクトップディレクトリをコピーする。
・ホームにある自製アプリ用ディレクトリをコピーする(BBS Browserなど)。
・キー操作をWindows風に変更(Enterキー1回で確定できて便利)。
Microsoft AutoUpdateを取り消す。
・iCloudカレンダーを共有する。
・Time Machineを設定する。
・フォントのギザギザが気になる場合はモニターのアンチエイリアスを有効にする(参考記事リンク)。

4.メール環境の移行
以下ディレクトリの内容をバックアップ(起動ディスク)から上書きする。メール設定のルールを開き、左端のチェックボックスをONにする。
 ~/Library/Accounts/
 ~/Library/Containers/com.apple.mail (なくても問題なし)
 ~/Library/Mail/ (macOSのバージョンが違う場合は不要)
 ~/Library/Mail/Vx/MailData/SmartMailboxesLocalProperties.plist (メール振分け設定)
 ~/Library/Preferences/com.apple.accounts.plist
 ~/Library/Preferences/com.apple.accountsd.plist
 ~/Library/Preferences/com.apple.mail-shared.plist
 ~/Library/Preferences/com.apple.mail.plist (なくても問題なし)

5.アプリをインストール
Xcode、Excel、VScodeなど常用アプリをインストールする。

6.C++開発環境を導入
Homebrew以外のライブラリをGitHubなどからインストールし、C++プロジェクトからmakefileでビルドできるようにする。今回はwxWidgetsをGitHubからダウンロード、ビルドした(下記記事参照)。

7.Pythonを導入
・最新のPythonを公式サイトからダウンロードして、インストールする(今回は3.13.0)。
・pythonコマンドでpython3が動作するようにシンボリックリンクを作成する。pipコマンドも同様。

sudo ln -s /usr/local/bin/python3 /usr/local/bin/python

sudo ln -s /usr/local/bin/pip3 /usr/local/bin/pip

・適当なスクリプトを実行して足りないライブラリをpipコマンドで導入する。

8.Java JREをインストール
Eclipse TemurinのサイトからJREをダウンロードしインストールする。

9.残りの作業
起動ディスクのファイル構成をFinderで確認しながら、足りないアプリを順次インストールする。

ゆっくり時間をかけて2日で前環境の主要な部分を再構成できました。前環境は起動ディスクとして残しているので、至急の際はこちらで対応できます。起動ディスク環境では最初音が出ませんでしたが、ヘッドホンジャック挿し直しで出るようになりました。

手間はかかりますが、工夫次第で本体1TB(プラス外部2TB)でも開発環境の維持は可能なようです。

キー操作をWindows風にする

24/11/28追記
macOS Sequoia 15.1.1にアップグレードして数日後クラッシュ。もう懲りたのでSonomaをインストールしてもらいAppleリペアセンターから受取(Apple Store持ち込みの翌々日)。再度環境構築開始。Sequoiaの次のOSがリリースされるまでSonomaを使う。

.bash_profileの条件分岐 カレントディレクトリによるPATH優先順位変更

[Mac M2 Pro 12CPU, Sonoma 14.3.1, clang++ 15.0.0]

以前の記事”[AI] ローカルLLM検証 llama.cppのmake時にSegmentation fault:11発生 macOS”で.bash_profileを書き換え、PATHの優先順位を変えました。

何らかの弊害があるだろうと思っていましたが、早速問題が表出しました。

pythonコマンドで/usr/local/binにある普段使いのPython3.10.4ではなく、/usr/binにあるPython3.9.6(macOSのデフォルト)が呼び出されるようになりました。

ChatGPTに解決方法を教えてもらい、以下のように.bash_profileを書き換えました。

PROMPT_COMMAND="check_for_llama_cpp"
check_for_llama_cpp() {
    # grepファイルを読み込めるようにする
    export PATH=/usr/bin:$PATH

    if ls | grep -q "llama.cpp"; then
        # 'llama.cpp' を含むディレクトリの場合
        export PATH=/usr/local/bin:$PATH
        export PATH=/usr/bin:$PATH
    else
        # それ以外のディレクトリの場合
        export PATH=/usr/bin:$PATH
        export PATH=/usr/local/bin:$PATH
    fi
}

これでllama.cppをビルドする時だけPATHの優先順位が変わり、/usr/binが優先されます。カレントディレクトリが変わる度にPROMPT_COMMANDによるチェックが入る仕組みです。その度にPATHデータが増えていきますが、パフォーマンスに影響はないでしょう。

[Xcode] アイコン登録 iOSとmacOSの違い 黒枠付きになる

[M1 Mac, Ventura 13.3.1, Xcode 14.3]

iOSアプリのアイコンとしてmacOSアプリで使ったアイコンと同サイズのものを登録すると下図のように黒枠で囲まれてやや小さいアイコンになりました。

黒枠付きアイコン(左側)

調べると、iOSの方は正方形の画像を登録しXcodeが角丸のアイコンにトリミングしてくれる仕組みであることが分かりました。

引用元:Apple Developer Documentation

iOSアプリ開発者の手間を軽減するようAppleが配慮しているということでしょうか。売上の半分以上を占めるiPhoneならさもありなんといったところです。

かといってmacOSアプリ開発者の方からiOSに合わせろという声は上がらないでしょう。アイコンも製作物の一部ですし角丸にするくらい自分でできる、と思っているのでは。

黒枠がとれたアイコン

[Xcode] printデバッグ時のコンソール表示

[M1 Mac, Ventura 13.3.1, Xcode 14.3]

Xcodeの独特なUIのおかげで足止めを食らったので記録しておきます。

何かの拍子にDebug AreaのVariables Viewボタンを押してしまったためにコンソールが表示できず、しばらく右往左往しました。

Debug Area右下のView選択ボタンにホバーした際、ボタンを押した時の動作がポップアップ表示されるのですが、非常に紛らわしいです。自分なら今現在の状態、例えば”Console Active”と表示させます。ボタンのラベルならともかく、ポップアップにボタン動作を表示させるのは私的には御法度です。

青色だからActiveだというのは分からないことはないものの、どうもしっくりきません。またデフォルトでは左右表示ですから元に戻すボタンが欲しいところです。

高機能ゆえに仕方がないことかもしれませんが、本当に初心者泣かせなUIです。この分かりにくさはDAWアプリのCubaseに通じるところがありますね。

IDEを使うとどうしても不満たらたらになってしまいます。iOSアプリを非IDE環境で作るのはハードルが高すぎるので我慢するしかありません。

Variables Viewのみ表示
Variables Viewとコンソール表示

[Swift] 27 iOSアップデート時のWatch Appトラブル

[M1 Mac, Ventura 13.3.1, Xcode 14.3]

iOSとwatchOSをそれぞれ16.5.1、9.5.2にアップデートしたところWatch Appが消えてしまいました。Watch App with iOS Appの方は残っています。

自製Watch Appを全て消して再インストールしようとするとApple Watchを認識できないとか色々難癖を付けてきます。

結局Mac、iPhone、Apple Watchを全て再起動すると直りました。最初からそう言ってほしいものです。

この手のトラブルは以前から発生しているようでApple開発者フォーラムでも非難囂々です。ちなみにMacとiPhoneはUSBハブ経由ではなく直接つなぐ方がいいらしいです。

[AI] ChatRWKVアプリ製作 その12 Mac版メモリ制限解除

[M1 Mac, Ventura 13.3.1, Python 3.10.4, PyTorch 2.0.0]

Mac版を改良しメモリの制限を解除できるようにしました。

def loadModel(self):
    self.box.setStyleSheet('background-color: #3E62AD')
    self.output.setText("")
    
    # PyTorch環境変数設定
    limitoffChecked = self.limit.isChecked()
    
    if limitoffChecked == True:
        os.environ['PYTORCH_MPS_HIGH_WATERMARK_RATIO'] = '0.0'
    else:
        try:
            del os.environ['PYTORCH_MPS_HIGH_WATERMARK_RATIO']
        except:
            pass

    try:
        print(f'PYTORCH_MPS_HIGH_WATERMARK_RATIO = {os.environ["PYTORCH_MPS_HIGH_WATERMARK_RATIO"]}\n')
    except:
        print('PYTORCH_MPS_HIGH_WATERMARK_RATIOは設定なし\n')

<以下略>

[AI] ChatRWKVアプリ製作 その11 M1 Mac / Metalで再挑戦

[M1 Mac, Ventura 13.3.1, Python 3.10.4, PyTorch 2.0.0]

ChatRWKVの設定により7Bサイズのモデルを読み込めるようになりました。

環境変数 PYTORCH_MPS_HIGH_WATERMARK_RATIOをゼロに設定しメモリ使用の上限を撤廃することで読込が可能になります。ただしシステムが不安定になる可能性があるため要注意です。

動作はかなり遅く実用にはほど遠いですが、RAMメモリ強化でどこまで速くなるのか興味深いです。

ところでAppleのイベントWWDCが今晩開催されますが(日本時間6/6 午前2時)、AIについてどのような発信があるのか楽しみです。

またグランフロント大阪にApple Storeを出店する計画があるとか。実現したらヨドバシ梅田と同様に売り上げ日本一になるのでは。

import os

# PyTorch環境変数設定
os.environ['PYTORCH_MPS_HIGH_WATERMARK_RATIO'] = '0.0'
print(f'PYTORCH_MPS_HIGH_WATERMARK_RATIO = {os.environ["PYTORCH_MPS_HIGH_WATERMARK_RATIO"]}\n')
self.stratChoice = QComboBox(self)
self.stratChoice.setGeometry(215,70,100,25)
self.stratChoice.addItem('mps fp32 -> cpu fp32 *10')
self.stratChoice.addItem('mps fp32')
self.stratChoice.addItem('cpu fp32')
self.stratChoice.addItem('cuda fp16')
7Bでは環境変数を変更しないとエラーになる
環境変数変更で7Bは読み込めたが動作はかなり遅い