boost::multi_arrayのランダムアクセスに注意
※下記の内容はVisual Studio2010でコンパイルしました。gcc 4.8.2でコンパイルすると結果が異なります。詳しくはコメント欄をご確認下さい。
便利なboost::multi_array
多次元配列を実装するときに便利なboost::multi_arrayですが、ランダムアクセスが遅いので注意が必要です。 この件について意外と情報が少なかったのでまとめてみました。
サンプルプログラム
#include "stdafx.h" #include <iostream> #include <boost/timer.hpp> #include <boost/multi_array.hpp> int _tmain(int argc, _TCHAR* argv[]) { boost::multi_array<int, 3> multiArray( boost::extents[500][500][500] ); boost::timer t; t.restart(); for ( int i = 0 ; i < multiArray.shape()[0] ; ++i ) { for ( int j = 0 ; j < multiArray.shape()[1] ; ++j ) { for ( int k = 0 ; k < multiArray.shape()[2] ; ++k ) { multiArray[i][j][k] = i + j + k; } } } std::cout << "ijk time = " << t.elapsed() << std::endl; t.restart(); for ( int k = 0 ; k < multiArray.shape()[2] ; ++k ) { for ( int j = 0 ; j < multiArray.shape()[1] ; ++j ) { for ( int i = 0 ; i < multiArray.shape()[0] ; ++i ) { multiArray[i][j][k] = i + j + k; } } } std::cout << "kji time = " << t.elapsed() << std::endl; t.restart(); int* it = multiArray.origin(); for ( int i = 0 ; i < multiArray.shape()[0] ; ++i ) { for ( int j = 0 ; j < multiArray.shape()[1] ; ++j ) { for ( int k = 0 ; k < multiArray.shape()[2] ; ++k, ++it ) { *it = i + j + k; } } } std::cout << "iterator time = " << t.elapsed() << std::endl; return 0; }
実行結果
ijk time = 2.293 kji time = 3.883 iterator time = 0.074
iteratorを使用することによって、ランダムアクセスより10倍以上速くなっています。