SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
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