groonga / grnxx

groonga++
Other
7 stars 0 forks source link

Gnx: Groonga に対する分散 load の並列化を評価する #156

Closed s-yata closed 9 years ago

s-yata commented 9 years ago

概要

与えられたデータを複数の Groonga DB に分けて load するとき,並列化によって高速化を実現できるか評価します.

データの分配については, _key があるときはハッシュ値, _key がないときは擬似乱数を使って格納する DB を選ぶようにします.

入力には Groonga コマンドと同様の書式を使います. そのため,分散させるときは,与えられたデータ(JSON)をパースして,分散させた後に JSON 化しなおすことになります. パースは並列化できませんが, JSON 化については並列化することができます.

s-yata commented 9 years ago

テスト環境

テーブル構成

table_create Table TABLE_NO_KEY
column_create Table Col0 COLUMN_SCALAR Bool
column_create Table Col1 COLUMN_SCALAR Int16
column_create Table Col2 COLUMN_SCALAR Float
column_create Table Col3 COLUMN_SCALAR ShortText

データ

コマンド内容

100 万行を 10 行ずつ入力します. 1 行ずつでない理由は,コマンド単位で並列化をおこなうためです. 以下に例を示します.

load --table Table --columns 'Col0,Col1,Col2,Col3' --values '[[false,5711,0.6645600532184904,"939984059"],[true,26840,0.06563701921747622,"336122540"],[false,27545,0.5152126285020654,"1747278511"],[false,29140,0.31805817433032985,"1006933274"],[false,7451,0.6790846759202163,"469339106"],[true,1604,0.5706732760710226,"1852186258"],[false,4677,0.7525730355516119,"443632888"],[false,23003,0.5238203060500009,"60780408"],[true,22507,0.9752416188605784,"170625356"],[true,28219,0.692024587353112,"647515026"]]'
s-yata commented 9 years ago

結果

残念ながら,分散や並列化による高速化は実現できませんでした. むしろ,オーバーヘッドが大きく,大幅に遅くなってしまいました. 索引なしの単純なテーブルでは,効果は期待できないようです.

全文検索用の転置索引があれば,コマンドの実行にかかる時間が長くなるため,並列化による効果が期待できます.

分散なし

まずは,データを分散させず,単一の DB に格納(load)するのに要した時間です.

1 DB
1 core 2.9s

分散あり,並列化なし

次に,複数 DB に分散させた結果です. パースして JSON 化しなおす手間が追加され,さらにコマンドの実行回数が増えるため,かなり遅くなっています.

1 DB 2 DBs 3 DBs 4 DBs
1 core 8.9s 10.3s 11.9s 13.4s

分散あり,並列化あり

JSON 化とコマンドの実行に goroutine を使うようにしました. また, runtime.GOMAXPROCS(NCPU) により並列度を変更しました.

1 DB 2 DBs 3 DBs 4 DBs
1 core 9.3s 11.8s 14.6s 16.8s
2 cores 14.1s 19.2s 19.6s 21.4s
3 cores 14.3s 19.8s 21.3s 22.6s
4 cores 14.2s 20.3s 22.3s 23.0s
s-yata commented 9 years ago

設定変更

全文検索索引があるとどうかを確かめるため,新しい設定を用意しました.

テーブル構成

全文検索索引を追加しました.

table_create Table TABLE_NO_KEY
column_create Table Col0 COLUMN_SCALAR Bool
column_create Table Col1 COLUMN_SCALAR Int16
column_create Table Col2 COLUMN_SCALAR Float
column_create Table Col3 COLUMN_SCALAR Text
table_create Idx3 TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram
column_create Idx3 Idx COLUMN_INDEX|WITH_POSITION Table Col3

データ

Col0, Col1, Col2 はそのままで, Col3 には日本語版 Wikipedia の本文から段落を切り出して入力しました. 平均長は 100 bytes 程度です.

コマンド内容

先のテストとほぼ同様ですが,実行時間の関係から合計 10 万行に減らしました. 入力は 10 行ずつなので,コマンドは 1 万件となります.

s-yata commented 9 years ago

結果

並列化により高速化できることもありそうな…という微妙な結果になりました. 現状では,まだ分散なしの方が良さそうです.

分散なし

まずは,データを分散させず,単一の DB に格納(load)するのに要した時間です. 転置索引を更新するため,先の実験と比べて桁ひとつ長い時間がかかっています.

1 DB
1 core 5.5s

分散あり,並列化なし

元のコマンドが重いため,分散によるオーバーヘッドの割合が小さくなっています.

1 DB 2 DBs 3 DBs 4 DBs
1 core 6.6s 7.6s 7.7s 8.1s

分散あり,並列化あり

並列化により高速化されるケースもあるようです. しかし,わざわざ並列化をおこなうほどの効果は得られませんでした.

1 DB 2 DBs 3 DBs 4 DBs
1 core 7.1s 7.7s 8.5s 8.6s
2 cores 7.8s 6.8s 7.3s 7.5s
3 cores 7.7s 7.2s 6.9s 7.0s
4 cores 7.7s 7.3s 7.3s 7.2s

シングルスレッドと比べれば遅くなっていますが,全文検索用の転置索引があれば,並列化により遅くなることはないようです. しかし,今回は平均長 100 bytes の Text を 10 行ずつ入れるという条件なので, Text が短くなったり一度に入力する行数が少なくなったりすれば,残念な結果になるかもしれません.

s-yata commented 9 years ago

結果(追加)

上のテストに追加で,一度に入力する行数を変更するとどうなるかを調べてみました. やはり,行数を減らすと効率が悪いようです(※). 一方で,コマンドが重ければ,実行時間を短縮できることがわかりました.

※ コマンド単位で並列化するので,そもそも並列化ができなくなってしまいます.

#rows/cmd load 1 DB, 1 core 4 DBs, 4 cores
1 7.0s 11.2s 15.7s
2 7.1s 9.0s 13.5s
4 6.6s 8.0s 10.3s
8 6.0s 8.1s 7.9s
16 5.7s 7.5s 6.2s
32 5.5s 7.0s 5.0s
64 5.5s 6.5s 4.3s
128 5.5s 6.5s 3.9s
s-yata commented 9 years ago

改良の余地について

軽いコマンドではオーバーヘッドが厳しいこと,重いコマンドでは時間が短縮できることがわかっています. いずれにせよ,オーバーヘッドを抑えることが高速化につながるはずです.

s-yata commented 9 years ago

別マシンで同様のテストをしてみます.

s-yata commented 9 years ago

Xeon E5-2643 3.3GHz (up to 3.5GHz) x2 な環境で試してみました. 並列度を高めれば並列化の効果も上がるかと思いきや,オーバーヘッドも増えてしまったようで,期待通りの結果にはなりませんでした. どちらかといえば悪化しています.

結果(索引なし)

分散・並列化なしでは以下の結果になりました.

1 DB
1 core 6.0s

分散・並列化ありでは以下の結果になりました.

1 DB 2 DBs 3 DBs 4 DBs 5 DBs 6 DBs 7 DBs 8 DBs
1 core 13.3s 16.6s 20.2s 22.9s 25.1s 27.3s 27.7s 29.8s
2 cores 15.6s 35.5s 49.9s 49.7s 56.6s 52.7s 49.9s 52.7s
3 cores 16.2s 38.5s 36.1s 43.5s 47.4s 48.1s 54.1s 53.2s
4 cores 16.3s 38.4s 38.5s 38.0s 43.6s 45.7s 47.9s 47.1s
5 cores 16.8s 38.8s 39.4s 39.0s 39.1s 40.8s 42.6s 45.3s
6 cores 16.5s 38.2s 39.0s 38.8s 39.7s 40.5s 40.8s 41.5s
7 cores 16.4s 37.8s 29.2s 38.9s 40.1s 42.1s 42.1s 41.2s
8 cores 16.5s 37.4s 38.3s 40.8s 41.5s 42.0s 43.6s 43.8s

結果(全文検索索引あり)

分散・並列化なしでは以下の結果になりました.

1 DB
1 core 8.6s

分散・並列化ありでは以下の結果になりました.

1 DB 2 DBs 3 DBs 4 DBs 5 DBs 6 DBs 7 DBs 8 DBs
1 core 9.7s 10.1s 10.9s 11.3s 11.9s 12.9s 12.2s 12.5s
2 cores 10.3s 14.6s 14.1s 13.6s 14.8s 14.5s 12.8s 13.3s
3 cores 10.3s 17.7s 16.7s 16.0s 13.9s 14.7s 15.5s 16.5s
4 cores 10.3s 17.9s 17.6s 16.0s 16.4s 15.8s 15.3s 15.0s
5 cores 10.1s 18.9s 17.8s 17.2s 16.0s 16.1s 15.3s 14.7s
6 cores 10.1s 17.7s 16.9s 16.6s 16.3s 15.8s 15.5s 15.7s
7 cores 10.3s 17.8s 17.6s 16.7s 16.8s 16.2s 16.0s 16.0s
8 cores 10.4s 17.8s 17.3s 17.1s 16.7s 16.3s 16.1s 16.0s

最後に,一度に入力する行数を変更した結果です. cores は 8 に固定しました.

1 DB 2 DBs 4 DBs 8 DBs
1 row 18.1s 18.4s 18.8s 19.1s
2 rows 13.9s 32.0s 31.3s 30.1s
4 rows 11.6s 24.0s 23.8s 22.3s
8 rows 10.5s 19.8s 18.5s 17.4s
16 rows 9.8s 15.5s 13.8s 13.1s
32 rows 9.5s 12.6s 10.2s 10.1s
64 rows 9.3s 10.0s 7.5s 7.2s
128 rows 9.0s 9.0s 6.0s 5.8s