24.
24
局所的でないメモリアクセスを避ける
局所的でないメモリアクセスをすると、アクセスする
データがキャッシュに乗っている確率が低くなる
例 ) 行列積
for (int i = 0; i < ROWS; ++i)
for (int j = 0; j < COLS; ++j)
for (int k = 0; k < LEN; ++k)
C[i][j] += A[i][k] * B[k][j];
二次元配列 B に ROWS 要素飛びでアクセスしている
25.
25
局所的でないメモリアクセスを避ける
局所的でないメモリアクセスをすると、アクセスする
データがキャッシュに乗っている確率が低くなる
例 ) 行列積
for (int i = 0; i < ROWS; ++i)
for (int k = 0; k < LEN; ++k)
for (int j = 0; j < COLS; ++j)
C[i][j] += A[i][k] * B[k][j];
全ての配列に順番にアクセスするようになった
入れ替えた
26.
26
データ構造を SoA に
大量のデータを順番に処理するとき、
AoS(Array of Structs; 構造体の配列 ) よりも、
SoA(Struct of Arrays; 配列の構造体 ) の方が高速に動作
する可能性がある
27.
27
データ構造を SoA に
例
struct data {
int a, b, c;
double x, y, z;
} d_ary[SIZE]; // AoS
int a[SIZE], b[SIZE], c[SIZE];
double x[SIZE], y[SIZE], z[SIZE]; //SoA
29.
29
SoA のデメリットと対策
多数の要素を読み取って計算しなければならない場合、
キャッシュラインを使い尽くしてしまい、逆に遅くなる
場合もある
SoA と AoS の適切なハイブリッド構造にすることが必要
頻繁に同時にアクセスする要素を一つの構造体に、など
30.
30
ストリップマイニング
以下のコードを考える
for (int i = 0; i < SIZE; ++i) {
hoge(A[i]);
}
for (int i = 0; i < SIZE; ++i) {
fuga(A[i]);
}
配列 A が十分長いとき、最初のループが終わった時点で、
A の先頭はキャッシュから排出されている
51.
51
C 言語でのビット演算
// ビット演算は整数型に対してのみ使える
A = B & C;
A &= B;
A = B << 4; // 下位ビットには 0 が詰められる
A <<= 4;
A = ~B;
// 符号なし 64 ビットリテラルを扱うとき
A = UINT64_C(0xCCCCCCCCCCCCCCCC);
62.
62
複数のビットから成るデータの配列の
ハミング距離を求める
例えば、 2 ビットから成るデータの配列のハミング距離
を求めるとき、
for (int i = 0; i < ARY_SIZE; ++i) {
uint8_t C = A[i] ^ B[i]; //8 ビットの場合
C = ((C & 0xAA) >> 1) | (C & 0x55);
result += popcount(C);
}
63.
63
立っている一番下のビットを求める
B = A & -A;
1 0 1 1 1 0 0 0A
0 1 0 0 1 0 0 0-A
0 0 0 0 1 0 0 0A & -A
-A = ~A + 1であることを利用
64.
64
立っている一番下のビットを中心に操作
A & (A – 1); // 立っている一番下のビットをクリア
A ^ -A; // 立っている一番下のビットより上の桁を 1 に
A | -A; // さらに立っている一番下のビットも 1 に
// 立っている一番下のビットより下の桁を 1 に
A ^ (A – 1)
65.
65
立っているビット列を走査する
// i &= i-1 で i の立っている一番下のビットをクリア
for (uint64_t i = bits; i != 0; i &= i-1) {
uint64_t rmb = i & -i;
// 何らかの処理
}
立っているビットの数が少ない場合には、この方法でも
立っているビットの数を高速に数えられる
75.
75
ビット列を一部だけスワップする
Delta Swap という手法
長さが等しく、重複のないビット列をスワップする
* * * A B C * * * a b c * * * *
この幅をdeltaとする
0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
x
mask
ABCとabcをスワップする
deltaとmaskを予め求めておく
76.
76
ビット列を一部だけスワップする
Delta Swap という手法
長さが等しく、重複のないビット列をスワップする
* * * A B C * * * a b c * * * *
0 0 0 0 0 0 0 0 0 P Q R 0 0 0 0
x
b := (x ^ (x >> delta)) & mask
P = A^a, Q = B^b, R = C^cとなる
b
77.
77
ビット列を一部だけスワップする
Delta Swap という手法
長さが等しく、重複のないビット列をスワップする
* * * A B C * * * a b c * * * *
0 0 0 P Q R 0 0 0 P Q R 0 0 0 0
x
ABCとabcが入れ替わった(他のビットは変化なし)
c := b ^ (b << delta)
c
* * * a b c * * * A B C * * * *c ^ x
Be the first to comment