AVX2におけるpermute命令の使い方
AVX2命令セットには、ベクトル内の要素を再配置するためのpermute系命令が含まれる。整数および浮動小数点データに対して使用可能で、用途に応じて異なる関数が提供されている。
整数用:_mm256_permutevar8x32_epi32
この命令は、インデックスベクタに基づいて32ビット整数要素を再配置する。
#include <immintrin.h>
int main() {
__m256i src_vec = _mm256_setr_epi32(10, 20, 30, 40, 50, 60, 70, 80);
__m256i idx_vec = _mm256_setr_epi32(7, 6, 5, 4, 3, 2, 1, 0);
__m256i shuffled = _mm256_permutevar8x32_epi32(src_vec, idx_vec);
// 結果: [80, 70, 60, 50, 40, 30, 20, 10]
}
浮動小数点用:_mm256_permute_ps
この命令は、8ビット即値(コンパイル時定数)を使って8つのfloat要素を再配置する。
#include <immintrin.h>
int main() {
__m256 input = _mm256_setr_ps(1.1f, 2.2f, 3.3f, 4.4f,
5.5f, 6.6f, 7.7f, 8.8f);
__m256 output = _mm256_permute_ps(input, 0b11100100);
// 結果: [3.3, 4.4, 7.7, 8.8, 1.1, 2.2, 5.5, 6.6]
}
即値は右から2ビットずつ読み取られ、各ペアが元ベクタのインデックス(00=0番目, 01=1番目, ...)を指定する。上記例では0b11100100を右から2ビット単位で分割すると[00][01][10][11]となり、対応する要素が選択される。
OpenMPとMPIによる並列計算
OpenMPは共有メモリ型並列処理を実現し、単一ノード内のマルチコアCPUで効率的に動作する。一方MPI(Message Passing Interface)は分散メモリ環境向けで、複数ノード間の通信をサポートする。
円周率計算の並列化例(OpenMP)
ライプニッツ級数に基づく積分法でπを近似計算するコードをOpenMPで並列化する。
#include <stdio.h>
#include <omp.h>
#define STEPS 100000000
int main() {
double step = 1.0 / STEPS;
double total = 0.0;
#pragma omp parallel for reduction(+:total) private(step)
for (long i = 0; i < STEPS; ++i) {
double x = (i + 0.5) * step;
total += 4.0 / (1.0 + x * x);
}
double pi = step * total;
printf("Estimated π: %.10f\n", pi);
}
偽共有問題とその対策
複数スレッドが同一キャッシュライン上の異なる変数にアクセスすると、無駄なキャッシュ無効化が発生する(偽共有)。これを回避するには、パディングを挿入して各スレッドのデータが別キャッシュラインに配置されるようにする。
double partial_sums[MAX_THREADS][8] = {{0}}; // 各要素が64バイト境界に配置
// 使用時は partial_sums[tid][0] のみ利用
スケジューリング戦略
素数判定のような不均一な負荷を持つループでは、schedule(dynamic)が静的分割より効率的であることが多い。
#pragma omp for schedule(dynamic, 1000) reduction(+:count)
for (int n = 2; n <= LIMIT; ++n) {
if (is_prime(n)) count++;
}
代表的なWebフレームワーク
フロントエンド
- React: コンポーネントベースのUI構築
- Vue: 軽量で漸進的に採用可能
- Angular: フル機能のSPAフレームワーク
- Svelte: コンパイル時に最適化
バックエンド
- Express.js (Node.js): 最小限の設計
- Django (Python): 「バッテリー内蔵」哲学
- Flask (Python): マイクロフレームワーク
- Spring Boot (Java): 本番向け設定の自動化
- Gin (Go): 高速なHTTPルーティング
フルスタック技術スタック
- MERN: MongoDB, Express, React, Node.js
- MEAN: MongoDB, Express, Angular, Node.js
Bashスクリプトによる性能評価
複数のバイナリを実行し、実行時間をCSV形式で記録するスクリプト例:
#!/bin/bash
echo "Optimization,Time(sec)" > benchmark.csv
for opt in "-O1" "-O2" "-O3"; do
gcc $opt -fopenmp pi_compute.c -o pi_$opt
time=$( { time ./pi_$opt; } 2>&1 | grep real | awk '{print $2}' )
echo "$opt,$time" >> benchmark.csv
done
GCC最適化オプションの比較
| オプション | 特徴 | 主な最適化内容 |
|---|---|---|
-O1 |
バランス重視 | デッドコード削除、ループ不変式外だし、単純なインライン展開 |
-O2 |
速度優先 | 関数インライン化、ループ展開、グローバルCSE、分岐予測 |
-O3 |
最大速度 | 自動ベクトル化、ループ融合、積極的インライン、SLPベクトル化 |
-Os |
サイズ最適化 | -O2相当の最適化+コードサイズ削減(アライメント最適化の抑制など) |
-Ofast |
非厳格最適化 | -O3+-ffast-math(IEEE 754準拠を犠牲にした高速化) |
最適化レベルを上げるとコンパイル時間が増加し、場合によっては数値精度やデバッグ性が低下する可能性があるため、用途に応じた選択が必要である。