# 機能設計書 142-OpenBLAS_jll

## 概要

本ドキュメントは、Julia標準ライブラリに含まれるOpenBLAS_jllパッケージの機能設計を記述する。OpenBLAS_jllは、OpenBLASライブラリのJLLバイナリラッパーであり、BLAS（Basic Linear Algebra Subprograms）およびLAPACK（Linear Algebra PACKage）の高速実装をJuliaから利用可能にする。

### 本機能の処理概要

OpenBLAS_jllは、OpenBLAS Cライブラリ（libopenblas）のプリビルドバイナリをJuliaのパッケージシステムを通じて提供するJLLラッパーパッケージである。64ビットBLASインデックス（ILP64）と32ビットBLASインデックス（LP64）の切り替え、プラットフォーム別のライブラリ名マッピング、OpenBLASのスレッド数制御を含む初期化処理を行う。

**業務上の目的・背景**：JuliaのLinearAlgebra標準ライブラリは、行列演算の高性能実装としてOpenBLASを使用する。OpenBLAS_jllは、このOpenBLASライブラリのバイナリ配布と動的リンクを管理し、CPU親和性やスレッド数の初期設定を行う。科学技術計算・機械学習・統計処理など、線形代数演算を多用するワークロードの性能基盤として不可欠である。

**機能の利用シーン**：行列乗算、LU分解、QR分解、SVD、固有値計算などのLinearAlgebra操作時にOpenBLASが内部的に呼び出される。Julia起動時にシステムイメージの一部として自動ロードされ、LinearAlgebra.__init__()でスレッド数が適切に設定される。

**主要な処理内容**：
1. BLAS64モード（ILP64）/BLAS32モード（LP64）に応じたライブラリサフィックスの決定
2. プラットフォーム（Windows/macOS/Linux）に応じたlibopenblas共有ライブラリパスの解決
3. 依存ライブラリ（CompilerSupportLibraries_jll: libgfortran, libgcc_s, libquadmath）の自動ロード
4. OpenBLAS環境変数（OPENBLAS_MAIN_FREE, OPENBLAS_NUM_THREADS等）の初期設定
5. `LazyLibrary`メカニズムを用いた遅延ライブラリロード

**関連システム・外部連携**：CompilerSupportLibraries_jll（Fortranランタイム、GCCランタイム）への依存。libblastrampoline（BLAS/LAPACKディスパッチレイヤー）経由でのアクセス。上流のOpenBLASプロジェクト（https://github.com/OpenMathLib/OpenBLAS）のバージョン0.3.30に対応。

**権限による制御**：特になし。全ユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はUI画面を持たない。LinearAlgebra経由でBLAS/LAPACK演算時に内部的に使用される |

## 機能種別

データ連携（ネイティブライブラリバイナリ配布・動的リンク管理・環境変数制御）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Base.USE_BLAS64 | Bool | Yes | 64ビットBLASインデックスの使用有無 | true/false |
| Sys.KERNEL | Symbol | Yes | 実行プラットフォームのカーネル識別子 | Windows/macOS/Linuxのいずれか |
| ENV["OPENBLAS_MAIN_FREE"] | String | No | OpenBLAS CPU親和性設定 | "0"または"1" |
| ENV["OPENBLAS_NUM_THREADS"] | String | No | OpenBLASスレッド数 | 正の整数文字列 |

### 入力データソース

- コンパイル時定数: `Base.USE_BLAS64` によるBLASインデックスサイズ判定
- プラットフォーム情報: `Sys.iswindows()`, `Sys.isapple()` による実行時判定
- 環境変数: OPENBLAS_MAIN_FREE, OPENBLAS_NUM_THREADS, GOTO_NUM_THREADS, OMP_NUM_THREADS

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| libopenblas | LazyLibrary | libopenblas共有ライブラリへのハンドル（遅延ロード） |
| libopenblas_path | String | libopenblasの絶対ファイルパス |
| artifact_dir | String | アーティファクトディレクトリ（Juliaプレフィックスディレクトリ） |
| libsuffix | String | BLASモードに応じたライブラリサフィックス（"64_" または ""） |

### 出力先

- メモリ内グローバル変数としてモジュール内に保持
- 環境変数（OPENBLAS_MAIN_FREE, OPENBLAS_DEFAULT_NUM_THREADS）の設定

## 処理フロー

### 処理シーケンス

```
1. モジュール定義（baremodule）
   └─ CompilerSupportLibraries_jll, Libdl, Base をusing
2. BLASモード判定（USE_BLAS64）
   └─ libsuffix = "64_" または ""
3. プラットフォーム判定によるライブラリパス決定
   └─ BundledLazyLibraryPathでOS別のlibopenblasファイル名を設定
4. LazyLibrary定数の定義
   └─ 依存ライブラリ（libgfortran, libgcc_s, libquadmath）をOS別に指定
5. __init__()実行（モジュールロード時）
   ├─ OPENBLAS_MAIN_FREE環境変数の設定（未設定の場合"1"）
   ├─ OPENBLAS_DEFAULT_NUM_THREADS環境変数の設定（未設定の場合"1"）
   └─ libopenblas_path, artifact_dir, LIBPATH の設定
```

### フローチャート

```mermaid
flowchart TD
    A[モジュールロード] --> B{USE_BLAS64?}
    B -->|true| C["libsuffix = '64_'"]
    B -->|false| D["libsuffix = ''"]
    C --> E{プラットフォーム判定}
    D --> E
    E -->|Windows| F["libopenblas64_.dll"]
    E -->|macOS| G["libopenblas64_.dylib"]
    E -->|Linux| H["libopenblas64_.so"]
    F --> I["__init__() 実行"]
    G --> I
    H --> I
    I --> J{OPENBLAS_MAIN_FREE設定済み?}
    J -->|No| K["ENV['OPENBLAS_MAIN_FREE'] = '1'"]
    J -->|Yes| L[スキップ]
    K --> M{OPENBLAS_NUM_THREADS等 設定済み?}
    L --> M
    M -->|No| N["ENV['OPENBLAS_DEFAULT_NUM_THREADS'] = '1'"]
    M -->|Yes| O[スキップ]
    N --> P[パス変数設定]
    O --> P
    P --> Q[初期化完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-142-01 | BLAS64モード | USE_BLAS64=trueの場合、ライブラリ名に"64_"サフィックスを付与 | コンパイル時 |
| BR-142-02 | CPU親和性無効化 | OPENBLAS_MAIN_FREE未設定時に"1"を設定し、CPU親和性設定を防止 | __init__時 |
| BR-142-03 | スレッド数制限 | OPENBLAS/GOTO/OMP_NUM_THREADS未設定時にデフォルトスレッド数を1に制限 | __init__時 |
| BR-142-04 | プラットフォーム別依存 | macOSではaarch64の場合libgcc_sを除外、libquadmathを条件付き追加 | ライブラリロード時 |

### 計算ロジック

特になし。ライブラリの動的ロード、環境変数制御、パス解決のみ。

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | DLError | ライブラリファイルが見つからない | dlopen失敗時のOSエラーメッセージ表示 |

### リトライ仕様

リトライは行わない。ライブラリロード失敗は致命的エラーとして扱う。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- OpenBLASのスレッド数は初期化時に1に制限され、LinearAlgebra.__init__()で適切な値に更新される
- これにより、起動時の大量メモリ割り当てを回避する（参照: JuliaLang/julia#45434）

## セキュリティ考慮事項

- バンドルされたバイナリはJuliaインストールディレクトリ内のプライベート共有ライブラリディレクトリに格納
- 環境変数経由でスレッド数やCPU親和性が制御可能

## 備考

- バージョン: OpenBLAS 0.3.30+0
- UUID: 4536629a-c528-5b80-bd46-f80d51c5b363
- JuliaBinaryWrappersの上流リポジトリ: https://github.com/JuliaBinaryWrappers/OpenBLAS_jll.jl
- CPU親和性問題の参照: JuliaLang/julia#1070, JuliaLang/julia#9639
- メモリ過剰割り当て問題の参照: JuliaLang/julia#45434

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | libdl.jl | `base/libdl.jl` | LazyLibrary構造体とBundledLazyLibraryPathの定義 |

**読解のコツ**: OpenBLAS_jllはBLAS64モードの切り替えが特徴的。`Base.USE_BLAS64`はコンパイル時に決定される定数であり、ライブラリ名のサフィックスを決定する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | OpenBLAS_jll.jl | `stdlib/OpenBLAS_jll/src/OpenBLAS_jll.jl` | モジュール全体の定義（80行） |

**主要処理フロー**:
1. **4行目**: `baremodule OpenBLAS_jll` - モジュール定義開始
2. **6行目**: `using CompilerSupportLibraries_jll` - Fortranランタイム依存
3. **18-22行目**: `libsuffix`の決定。`Base.USE_BLAS64`に基づきBLAS64用サフィックスを設定
4. **25-47行目**: `libopenblas` LazyLibrary定数の定義。OS・アーキテクチャ別の依存指定
5. **33-46行目**: 依存ライブラリの条件分岐。Windows: libgfortran+libgcc_s、macOS: libgfortran+条件付きlibquadmath+条件付きlibgcc_s、Linux: libgfortranのみ
6. **56-78行目**: `__init__()` - 環境変数設定とパス初期化

#### Step 3: 初期化ロジックの詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | OpenBLAS_jll.jl | `stdlib/OpenBLAS_jll/src/OpenBLAS_jll.jl` | __init__()の環境変数制御（56-78行目） |

**主要処理フロー**:
- **59-61行目**: `OPENBLAS_MAIN_FREE`環境変数。未設定時に"1"を設定してCPU親和性を無効化
- **68行目**: 3つのスレッド数環境変数（OPENBLAS_NUM_THREADS, GOTO_NUM_THREADS, OMP_NUM_THREADS）すべてが未設定かチェック
- **71行目**: `OPENBLAS_DEFAULT_NUM_THREADS`を"1"に設定。LinearAlgebraの__init__()で後から更新される

#### Step 4: プラットフォーム別依存の理解

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | OpenBLAS_jll.jl | `stdlib/OpenBLAS_jll/src/OpenBLAS_jll.jl` | 依存ライブラリ指定（33-46行目） |

**主要処理フロー**:
- **37-38行目**: macOSでのlibquadmath条件付き依存。CompilerSupportLibraries_jllにlibquadmathが定義されている場合のみ追加
- **40-41行目**: macOSでaarch64以外の場合にlibgcc_sを追加

### プログラム呼び出し階層図

```
OpenBLAS_jll.__init__()
    |
    +-- ENV["OPENBLAS_MAIN_FREE"] = "1" (条件付き)
    |
    +-- ENV["OPENBLAS_DEFAULT_NUM_THREADS"] = "1" (条件付き)
    |
    +-- libopenblas.path (LazyLibrary.path アクセス)
    |       |
    |       +-- BundledLazyLibraryPath("libopenblas64_.so")
    |
    +-- artifact_dir = dirname(Sys.BINDIR)
    |
    +-- LIBPATH[] = dirname(libopenblas_path)

OpenBLAS_jll.eager_mode()
    |
    +-- CompilerSupportLibraries_jll.eager_mode()
    |       |
    |       +-- dlopen(libgfortran), dlopen(libgcc_s), ...
    |
    +-- dlopen(libopenblas_path)
```

### データフロー図

```
[入力]                              [処理]                              [出力]

Base.USE_BLAS64 -----------------> libsuffix決定 -----------------> ライブラリ名
Sys.KERNEL (OS種別) -------------> プラットフォーム判定 ----------> 依存ライブラリリスト
ENV (スレッド数設定) ------------> 環境変数チェック・設定 --------> ENV更新
Sys.BINDIR (Juliaパス) ----------> BundledLazyLibraryPath --------> libopenblas_path
CompilerSupportLibraries_jll ----> 依存ライブラリロード ----------> libopenblasハンドル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| OpenBLAS_jll.jl | `stdlib/OpenBLAS_jll/src/OpenBLAS_jll.jl` | ソース | メインモジュール定義。libopenblasのLazyLibrary定義と環境変数初期化 |
| Project.toml | `stdlib/OpenBLAS_jll/Project.toml` | 設定 | パッケージメタデータ・依存関係・バージョン情報 |
| libdl.jl | `base/libdl.jl` | ソース | LazyLibrary/BundledLazyLibraryPathの基盤実装 |
