6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++Advent Calendar 2017

Day 23

100万回の小規模行列の掛け算におけるメモリ配置と計算速度について

Last updated at Posted at 2017-12-22

C++を使っておりますが、テーマが大分それてしまいました。
カレンダーで、このタイトルだけ趣旨がずれて浮いてる気がしてます…失礼いたします…

#本稿でやったこと
 大量の小規模行列の掛け算に対し、2種類のメモリ配置を試し、どちらが計算速度が速いかを確認しました。
 いつも通り設計していたのですが、速度向上を図って試行錯誤していくうちに、C言語のようなソースコードになってしまいました。いずれ整えます。
 私はHPCの分野は素人ですので、ご意見頂けると有り難いです。

#背景
 ※これはテーマからかなり逸れるので、飛ばしても構いません。

 多くの工学分野の解析実務で、FEM(有限要素法)という数値解析手法が広く用いられています。FEMは振動解析や郷土解析などの構造計算の分野でも使われます。私は構造計算でFEMを使うことが多いため、今回それを前提とします。
 FEMによる数値解析においては、限られたリソースで高速に解く必要があり、効率の良いメモリ配置が重要と思います。FEMの書籍には、解説とともにサンプルプログラムが公開されているものがあります(例えば[1])。しかしその解説において、計算速度に対するメモリ配置の説明が無いと私は思っております。そこで、現状、私が想定している2種類のメモリ配置の方法について計算速度を確認し、今後の機会に活かそうかと思った次第です。
 ただし、HPCの分野でよく見られる大規模疎行列の計算の高速化ではなく、大量の小規模行列の演算に着目します。FEMの用途によっては、大量の小規模行列の演算が必要になるからです。

#FEMによる構造計算の手順の概説
 ※これもテーマからかなり逸れるので、飛ばしても構いません。

 例えば周波数応答の振動解析の場合、一般的な計算手順はおおよそ下記ようになります。

 1. 解析対象の物体を$n$個の要素に分割する。
 2. 着目したい周波数$ \omega_{j} $について次の計算を行う。
  2-1. 要素の係数行列$ \left[K_e^{,i},\right](i=1,...,n)$を計算する。
  2-2. n個の$\left[K_e^{,i},\right]$を全体係数行列$ \left[K_{global},\right]$にAssembleする。
  2-3. $ \left[K_{global},\right]$を左辺行列、入力を右辺ベクトルとした連立一次方程式を解き、出力を求める。
  2-4. 2-3の出力と、2-1の計算過程で得られた行列を用いて要素の特性値(応力、歪みなど)を求める。

 2-3の処理は、大規模データの場合、多くの解析プログラムにおいてクリティカルパスになることが多く、高速化の研究対象になっています。ここでは、余り議論の対象とならない2-1、2-4などの小規模行列の処理に着目します。現状この処理がプログラム全体の計算時間に占める割合は大きくないと思いますが、2-3が高速化されれば必然的にこの処理の割合が増えるので、検討の意義はあるかと思います。2-1の$ \left[K_e^{,i},\right]$は下式で計算されます。

$$
\left[K_e^{,i},\right]=\int_{\Omega_e^{,i}}\left[B_e^{,i},\right]^T\left[D_e^{,i},\right]\left[B_e^{,i},\right]d\Omega \tag{1}
$$

3つの行列の掛け算を積分した形になります。各行列が何を表すかの説明は省略します。
今回、100万要素の計算を前提とし、(1)式をi=1~100万まで100万回計算します。以前なら大規模、今なら中規模という要素数です。

#メモリ配置2案
 (1)式は3つの行列の掛け算と積分ですが、行列掛け算は単純化のため3つでなく2つとし、積分は数値積分で行うものとし、検討対象は次式とします。
$$\left[A^{,i},\right]\left[B^{,i},\right]=\left[X^{,i},\right] \tag{2} $$
行列サイズはそれぞれ6x6、6x24、6x24とします。これはFEMのHEXA要素の計算の一部を想定しています。
$\left[A^{,i}\right]$、$\left[B^{,i}\right]$、$\left[X^{,i}\right]$を下記2通りの方法(a),(b)で配置します。

 (a) ABXを1セットとして、n=100万回連続して格納する。
  $[A^{,1}],[B^{,1}],[X^{,1}],,,[A^{,2}],[B^{,2}],[X^{,2}],,,...,,,[A^{,n}],[B^{,n}],[X^{,n}] \tag{3} $

 (b) A,B,Xをそれぞれn=100万回連続して格納する。
     $[A^{,1}],[A^{,2}],,,...,,,[A^{,n}]$、 $[B^{,1}],[B^{,2}],,,...,,,[B^{,n}]$、 $[X^{,1}],[X^{,2}],,,...,,,[X^{,n}] \tag{4} $

 $[A^{,i}]$、$[B^{,i}]$、$[X^{,i}]$合わせて倍精度浮動小数点が324個なので、100万個分のメモリ使用量は約2.4GBとなります。キャッシュには乗らないので、メモリ配置の良し悪しでキャッシュヒット率が決まり、速度が決まる、という目論見です。(a)は一回の演算に使う行列ABXが連続して格納されているので、キャッシュヒット率が高くなり高速であると期待しておりました。

#実装
 まず、100万要素分のdouble型配列を準備します。

	constexpr size_t	nElm    = 1000000;	//	100万要素

	constexpr int		nAelm   = 36;		//	行列A(6x6)の成分数
	constexpr int		nBelm   = 144;		//	行列B(6x24)の成分数
	constexpr int		nXelm   = 144;		//	行列X(6x24)の成分数
	constexpr int		nElmAll = nBelm + nAelm + nXelm;	//	ABXの成分数の和324個

	constexpr size_t	nSize = nElm * nElmAll;			//	100万要素の行列成分数
	std::vector<double>	buf( nSize );					//	100万要素分のdouble型配列。メモリ使用量は nSize * 8byte = 約2.4GB

値は乱数で初期化しておきます。

	//	-1.0~1.0の乱数設定
	{
		std::random_device	seed_gen;
		std::mt19937		engine( seed_gen() );

		for( size_t i = 0; i < nSize; ++i ){
			buf[ i ] = ( 2.0 * double( engine() ) / double( UINT32_MAX ) ) - 1.0;
		}
	}

固定長の2つの行列掛け算なので、ループは全て展開します。(a)(b)それぞれのAB=Xの掛け算関数の実装を次に示します。(a)では、A行列の先頭ポインタが分かればB、Xの先頭ポインタも分かるので、引数はAの先頭ポインタのみです。一方、(b)については、A,B,Xそれぞれの先頭ポインタが必要です。
(a)(b)の計算の実装はそれぞれ次のようになりました。ソースが長いので閉じております。

(a)の行列掛け算の実装
inline bool	mmultABX_a( double* pA )
{
	{
		pA[ 180 ] = pA[ 0 ] * pA[ 36 ] + pA[ 6 ] * pA[ 37 ] + pA[ 12 ] * pA[ 38 ] + pA[ 18 ] * pA[ 39 ] + pA[ 24 ] * pA[ 40 ] + pA[ 30 ] * pA[ 41 ];
		pA[ 181 ] = pA[ 1 ] * pA[ 36 ] + pA[ 7 ] * pA[ 37 ] + pA[ 13 ] * pA[ 38 ] + pA[ 19 ] * pA[ 39 ] + pA[ 25 ] * pA[ 40 ] + pA[ 31 ] * pA[ 41 ];
		pA[ 182 ] = pA[ 2 ] * pA[ 36 ] + pA[ 8 ] * pA[ 37 ] + pA[ 14 ] * pA[ 38 ] + pA[ 20 ] * pA[ 39 ] + pA[ 26 ] * pA[ 40 ] + pA[ 32 ] * pA[ 41 ];
		pA[ 183 ] = pA[ 3 ] * pA[ 36 ] + pA[ 9 ] * pA[ 37 ] + pA[ 15 ] * pA[ 38 ] + pA[ 21 ] * pA[ 39 ] + pA[ 27 ] * pA[ 40 ] + pA[ 33 ] * pA[ 41 ];
		pA[ 184 ] = pA[ 4 ] * pA[ 36 ] + pA[ 10 ] * pA[ 37 ] + pA[ 16 ] * pA[ 38 ] + pA[ 22 ] * pA[ 39 ] + pA[ 28 ] * pA[ 40 ] + pA[ 34 ] * pA[ 41 ];
		pA[ 185 ] = pA[ 5 ] * pA[ 36 ] + pA[ 11 ] * pA[ 37 ] + pA[ 17 ] * pA[ 38 ] + pA[ 23 ] * pA[ 39 ] + pA[ 29 ] * pA[ 40 ] + pA[ 35 ] * pA[ 41 ];
	}
	{
		pA[ 186 ] = pA[ 0 ] * pA[ 42 ] + pA[ 6 ] * pA[ 43 ] + pA[ 12 ] * pA[ 44 ] + pA[ 18 ] * pA[ 45 ] + pA[ 24 ] * pA[ 46 ] + pA[ 30 ] * pA[ 47 ];
		pA[ 187 ] = pA[ 1 ] * pA[ 42 ] + pA[ 7 ] * pA[ 43 ] + pA[ 13 ] * pA[ 44 ] + pA[ 19 ] * pA[ 45 ] + pA[ 25 ] * pA[ 46 ] + pA[ 31 ] * pA[ 47 ];
		pA[ 188 ] = pA[ 2 ] * pA[ 42 ] + pA[ 8 ] * pA[ 43 ] + pA[ 14 ] * pA[ 44 ] + pA[ 20 ] * pA[ 45 ] + pA[ 26 ] * pA[ 46 ] + pA[ 32 ] * pA[ 47 ];
		pA[ 189 ] = pA[ 3 ] * pA[ 42 ] + pA[ 9 ] * pA[ 43 ] + pA[ 15 ] * pA[ 44 ] + pA[ 21 ] * pA[ 45 ] + pA[ 27 ] * pA[ 46 ] + pA[ 33 ] * pA[ 47 ];
		pA[ 190 ] = pA[ 4 ] * pA[ 42 ] + pA[ 10 ] * pA[ 43 ] + pA[ 16 ] * pA[ 44 ] + pA[ 22 ] * pA[ 45 ] + pA[ 28 ] * pA[ 46 ] + pA[ 34 ] * pA[ 47 ];
		pA[ 191 ] = pA[ 5 ] * pA[ 42 ] + pA[ 11 ] * pA[ 43 ] + pA[ 17 ] * pA[ 44 ] + pA[ 23 ] * pA[ 45 ] + pA[ 29 ] * pA[ 46 ] + pA[ 35 ] * pA[ 47 ];
	}
	{
		pA[ 192 ] = pA[ 0 ] * pA[ 48 ] + pA[ 6 ] * pA[ 49 ] + pA[ 12 ] * pA[ 50 ] + pA[ 18 ] * pA[ 51 ] + pA[ 24 ] * pA[ 52 ] + pA[ 30 ] * pA[ 53 ];
		pA[ 193 ] = pA[ 1 ] * pA[ 48 ] + pA[ 7 ] * pA[ 49 ] + pA[ 13 ] * pA[ 50 ] + pA[ 19 ] * pA[ 51 ] + pA[ 25 ] * pA[ 52 ] + pA[ 31 ] * pA[ 53 ];
		pA[ 194 ] = pA[ 2 ] * pA[ 48 ] + pA[ 8 ] * pA[ 49 ] + pA[ 14 ] * pA[ 50 ] + pA[ 20 ] * pA[ 51 ] + pA[ 26 ] * pA[ 52 ] + pA[ 32 ] * pA[ 53 ];
		pA[ 195 ] = pA[ 3 ] * pA[ 48 ] + pA[ 9 ] * pA[ 49 ] + pA[ 15 ] * pA[ 50 ] + pA[ 21 ] * pA[ 51 ] + pA[ 27 ] * pA[ 52 ] + pA[ 33 ] * pA[ 53 ];
		pA[ 196 ] = pA[ 4 ] * pA[ 48 ] + pA[ 10 ] * pA[ 49 ] + pA[ 16 ] * pA[ 50 ] + pA[ 22 ] * pA[ 51 ] + pA[ 28 ] * pA[ 52 ] + pA[ 34 ] * pA[ 53 ];
		pA[ 197 ] = pA[ 5 ] * pA[ 48 ] + pA[ 11 ] * pA[ 49 ] + pA[ 17 ] * pA[ 50 ] + pA[ 23 ] * pA[ 51 ] + pA[ 29 ] * pA[ 52 ] + pA[ 35 ] * pA[ 53 ];
	}
	{
		pA[ 198 ] = pA[ 0 ] * pA[ 54 ] + pA[ 6 ] * pA[ 55 ] + pA[ 12 ] * pA[ 56 ] + pA[ 18 ] * pA[ 57 ] + pA[ 24 ] * pA[ 58 ] + pA[ 30 ] * pA[ 59 ];
		pA[ 199 ] = pA[ 1 ] * pA[ 54 ] + pA[ 7 ] * pA[ 55 ] + pA[ 13 ] * pA[ 56 ] + pA[ 19 ] * pA[ 57 ] + pA[ 25 ] * pA[ 58 ] + pA[ 31 ] * pA[ 59 ];
		pA[ 200 ] = pA[ 2 ] * pA[ 54 ] + pA[ 8 ] * pA[ 55 ] + pA[ 14 ] * pA[ 56 ] + pA[ 20 ] * pA[ 57 ] + pA[ 26 ] * pA[ 58 ] + pA[ 32 ] * pA[ 59 ];
		pA[ 201 ] = pA[ 3 ] * pA[ 54 ] + pA[ 9 ] * pA[ 55 ] + pA[ 15 ] * pA[ 56 ] + pA[ 21 ] * pA[ 57 ] + pA[ 27 ] * pA[ 58 ] + pA[ 33 ] * pA[ 59 ];
		pA[ 202 ] = pA[ 4 ] * pA[ 54 ] + pA[ 10 ] * pA[ 55 ] + pA[ 16 ] * pA[ 56 ] + pA[ 22 ] * pA[ 57 ] + pA[ 28 ] * pA[ 58 ] + pA[ 34 ] * pA[ 59 ];
		pA[ 203 ] = pA[ 5 ] * pA[ 54 ] + pA[ 11 ] * pA[ 55 ] + pA[ 17 ] * pA[ 56 ] + pA[ 23 ] * pA[ 57 ] + pA[ 29 ] * pA[ 58 ] + pA[ 35 ] * pA[ 59 ];
	}
	{
		pA[ 204 ] = pA[ 0 ] * pA[ 60 ] + pA[ 6 ] * pA[ 61 ] + pA[ 12 ] * pA[ 62 ] + pA[ 18 ] * pA[ 63 ] + pA[ 24 ] * pA[ 64 ] + pA[ 30 ] * pA[ 65 ];
		pA[ 205 ] = pA[ 1 ] * pA[ 60 ] + pA[ 7 ] * pA[ 61 ] + pA[ 13 ] * pA[ 62 ] + pA[ 19 ] * pA[ 63 ] + pA[ 25 ] * pA[ 64 ] + pA[ 31 ] * pA[ 65 ];
		pA[ 206 ] = pA[ 2 ] * pA[ 60 ] + pA[ 8 ] * pA[ 61 ] + pA[ 14 ] * pA[ 62 ] + pA[ 20 ] * pA[ 63 ] + pA[ 26 ] * pA[ 64 ] + pA[ 32 ] * pA[ 65 ];
		pA[ 207 ] = pA[ 3 ] * pA[ 60 ] + pA[ 9 ] * pA[ 61 ] + pA[ 15 ] * pA[ 62 ] + pA[ 21 ] * pA[ 63 ] + pA[ 27 ] * pA[ 64 ] + pA[ 33 ] * pA[ 65 ];
		pA[ 208 ] = pA[ 4 ] * pA[ 60 ] + pA[ 10 ] * pA[ 61 ] + pA[ 16 ] * pA[ 62 ] + pA[ 22 ] * pA[ 63 ] + pA[ 28 ] * pA[ 64 ] + pA[ 34 ] * pA[ 65 ];
		pA[ 209 ] = pA[ 5 ] * pA[ 60 ] + pA[ 11 ] * pA[ 61 ] + pA[ 17 ] * pA[ 62 ] + pA[ 23 ] * pA[ 63 ] + pA[ 29 ] * pA[ 64 ] + pA[ 35 ] * pA[ 65 ];
	}
	{
		pA[ 210 ] = pA[ 0 ] * pA[ 66 ] + pA[ 6 ] * pA[ 67 ] + pA[ 12 ] * pA[ 68 ] + pA[ 18 ] * pA[ 69 ] + pA[ 24 ] * pA[ 70 ] + pA[ 30 ] * pA[ 71 ];
		pA[ 211 ] = pA[ 1 ] * pA[ 66 ] + pA[ 7 ] * pA[ 67 ] + pA[ 13 ] * pA[ 68 ] + pA[ 19 ] * pA[ 69 ] + pA[ 25 ] * pA[ 70 ] + pA[ 31 ] * pA[ 71 ];
		pA[ 212 ] = pA[ 2 ] * pA[ 66 ] + pA[ 8 ] * pA[ 67 ] + pA[ 14 ] * pA[ 68 ] + pA[ 20 ] * pA[ 69 ] + pA[ 26 ] * pA[ 70 ] + pA[ 32 ] * pA[ 71 ];
		pA[ 213 ] = pA[ 3 ] * pA[ 66 ] + pA[ 9 ] * pA[ 67 ] + pA[ 15 ] * pA[ 68 ] + pA[ 21 ] * pA[ 69 ] + pA[ 27 ] * pA[ 70 ] + pA[ 33 ] * pA[ 71 ];
		pA[ 214 ] = pA[ 4 ] * pA[ 66 ] + pA[ 10 ] * pA[ 67 ] + pA[ 16 ] * pA[ 68 ] + pA[ 22 ] * pA[ 69 ] + pA[ 28 ] * pA[ 70 ] + pA[ 34 ] * pA[ 71 ];
		pA[ 215 ] = pA[ 5 ] * pA[ 66 ] + pA[ 11 ] * pA[ 67 ] + pA[ 17 ] * pA[ 68 ] + pA[ 23 ] * pA[ 69 ] + pA[ 29 ] * pA[ 70 ] + pA[ 35 ] * pA[ 71 ];
	}
	{
		pA[ 216 ] = pA[ 0 ] * pA[ 72 ] + pA[ 6 ] * pA[ 73 ] + pA[ 12 ] * pA[ 74 ] + pA[ 18 ] * pA[ 75 ] + pA[ 24 ] * pA[ 76 ] + pA[ 30 ] * pA[ 77 ];
		pA[ 217 ] = pA[ 1 ] * pA[ 72 ] + pA[ 7 ] * pA[ 73 ] + pA[ 13 ] * pA[ 74 ] + pA[ 19 ] * pA[ 75 ] + pA[ 25 ] * pA[ 76 ] + pA[ 31 ] * pA[ 77 ];
		pA[ 218 ] = pA[ 2 ] * pA[ 72 ] + pA[ 8 ] * pA[ 73 ] + pA[ 14 ] * pA[ 74 ] + pA[ 20 ] * pA[ 75 ] + pA[ 26 ] * pA[ 76 ] + pA[ 32 ] * pA[ 77 ];
		pA[ 219 ] = pA[ 3 ] * pA[ 72 ] + pA[ 9 ] * pA[ 73 ] + pA[ 15 ] * pA[ 74 ] + pA[ 21 ] * pA[ 75 ] + pA[ 27 ] * pA[ 76 ] + pA[ 33 ] * pA[ 77 ];
		pA[ 220 ] = pA[ 4 ] * pA[ 72 ] + pA[ 10 ] * pA[ 73 ] + pA[ 16 ] * pA[ 74 ] + pA[ 22 ] * pA[ 75 ] + pA[ 28 ] * pA[ 76 ] + pA[ 34 ] * pA[ 77 ];
		pA[ 221 ] = pA[ 5 ] * pA[ 72 ] + pA[ 11 ] * pA[ 73 ] + pA[ 17 ] * pA[ 74 ] + pA[ 23 ] * pA[ 75 ] + pA[ 29 ] * pA[ 76 ] + pA[ 35 ] * pA[ 77 ];
	}
	{
		pA[ 222 ] = pA[ 0 ] * pA[ 78 ] + pA[ 6 ] * pA[ 79 ] + pA[ 12 ] * pA[ 80 ] + pA[ 18 ] * pA[ 81 ] + pA[ 24 ] * pA[ 82 ] + pA[ 30 ] * pA[ 83 ];
		pA[ 223 ] = pA[ 1 ] * pA[ 78 ] + pA[ 7 ] * pA[ 79 ] + pA[ 13 ] * pA[ 80 ] + pA[ 19 ] * pA[ 81 ] + pA[ 25 ] * pA[ 82 ] + pA[ 31 ] * pA[ 83 ];
		pA[ 224 ] = pA[ 2 ] * pA[ 78 ] + pA[ 8 ] * pA[ 79 ] + pA[ 14 ] * pA[ 80 ] + pA[ 20 ] * pA[ 81 ] + pA[ 26 ] * pA[ 82 ] + pA[ 32 ] * pA[ 83 ];
		pA[ 225 ] = pA[ 3 ] * pA[ 78 ] + pA[ 9 ] * pA[ 79 ] + pA[ 15 ] * pA[ 80 ] + pA[ 21 ] * pA[ 81 ] + pA[ 27 ] * pA[ 82 ] + pA[ 33 ] * pA[ 83 ];
		pA[ 226 ] = pA[ 4 ] * pA[ 78 ] + pA[ 10 ] * pA[ 79 ] + pA[ 16 ] * pA[ 80 ] + pA[ 22 ] * pA[ 81 ] + pA[ 28 ] * pA[ 82 ] + pA[ 34 ] * pA[ 83 ];
		pA[ 227 ] = pA[ 5 ] * pA[ 78 ] + pA[ 11 ] * pA[ 79 ] + pA[ 17 ] * pA[ 80 ] + pA[ 23 ] * pA[ 81 ] + pA[ 29 ] * pA[ 82 ] + pA[ 35 ] * pA[ 83 ];
	}
	{
		pA[ 228 ] = pA[ 0 ] * pA[ 84 ] + pA[ 6 ] * pA[ 85 ] + pA[ 12 ] * pA[ 86 ] + pA[ 18 ] * pA[ 87 ] + pA[ 24 ] * pA[ 88 ] + pA[ 30 ] * pA[ 89 ];
		pA[ 229 ] = pA[ 1 ] * pA[ 84 ] + pA[ 7 ] * pA[ 85 ] + pA[ 13 ] * pA[ 86 ] + pA[ 19 ] * pA[ 87 ] + pA[ 25 ] * pA[ 88 ] + pA[ 31 ] * pA[ 89 ];
		pA[ 230 ] = pA[ 2 ] * pA[ 84 ] + pA[ 8 ] * pA[ 85 ] + pA[ 14 ] * pA[ 86 ] + pA[ 20 ] * pA[ 87 ] + pA[ 26 ] * pA[ 88 ] + pA[ 32 ] * pA[ 89 ];
		pA[ 231 ] = pA[ 3 ] * pA[ 84 ] + pA[ 9 ] * pA[ 85 ] + pA[ 15 ] * pA[ 86 ] + pA[ 21 ] * pA[ 87 ] + pA[ 27 ] * pA[ 88 ] + pA[ 33 ] * pA[ 89 ];
		pA[ 232 ] = pA[ 4 ] * pA[ 84 ] + pA[ 10 ] * pA[ 85 ] + pA[ 16 ] * pA[ 86 ] + pA[ 22 ] * pA[ 87 ] + pA[ 28 ] * pA[ 88 ] + pA[ 34 ] * pA[ 89 ];
		pA[ 233 ] = pA[ 5 ] * pA[ 84 ] + pA[ 11 ] * pA[ 85 ] + pA[ 17 ] * pA[ 86 ] + pA[ 23 ] * pA[ 87 ] + pA[ 29 ] * pA[ 88 ] + pA[ 35 ] * pA[ 89 ];
	}
	{
		pA[ 234 ] = pA[ 0 ] * pA[ 90 ] + pA[ 6 ] * pA[ 91 ] + pA[ 12 ] * pA[ 92 ] + pA[ 18 ] * pA[ 93 ] + pA[ 24 ] * pA[ 94 ] + pA[ 30 ] * pA[ 95 ];
		pA[ 235 ] = pA[ 1 ] * pA[ 90 ] + pA[ 7 ] * pA[ 91 ] + pA[ 13 ] * pA[ 92 ] + pA[ 19 ] * pA[ 93 ] + pA[ 25 ] * pA[ 94 ] + pA[ 31 ] * pA[ 95 ];
		pA[ 236 ] = pA[ 2 ] * pA[ 90 ] + pA[ 8 ] * pA[ 91 ] + pA[ 14 ] * pA[ 92 ] + pA[ 20 ] * pA[ 93 ] + pA[ 26 ] * pA[ 94 ] + pA[ 32 ] * pA[ 95 ];
		pA[ 237 ] = pA[ 3 ] * pA[ 90 ] + pA[ 9 ] * pA[ 91 ] + pA[ 15 ] * pA[ 92 ] + pA[ 21 ] * pA[ 93 ] + pA[ 27 ] * pA[ 94 ] + pA[ 33 ] * pA[ 95 ];
		pA[ 238 ] = pA[ 4 ] * pA[ 90 ] + pA[ 10 ] * pA[ 91 ] + pA[ 16 ] * pA[ 92 ] + pA[ 22 ] * pA[ 93 ] + pA[ 28 ] * pA[ 94 ] + pA[ 34 ] * pA[ 95 ];
		pA[ 239 ] = pA[ 5 ] * pA[ 90 ] + pA[ 11 ] * pA[ 91 ] + pA[ 17 ] * pA[ 92 ] + pA[ 23 ] * pA[ 93 ] + pA[ 29 ] * pA[ 94 ] + pA[ 35 ] * pA[ 95 ];
	}
	{
		pA[ 240 ] = pA[ 0 ] * pA[ 96 ] + pA[ 6 ] * pA[ 97 ] + pA[ 12 ] * pA[ 98 ] + pA[ 18 ] * pA[ 99 ] + pA[ 24 ] * pA[ 100 ] + pA[ 30 ] * pA[ 101 ];
		pA[ 241 ] = pA[ 1 ] * pA[ 96 ] + pA[ 7 ] * pA[ 97 ] + pA[ 13 ] * pA[ 98 ] + pA[ 19 ] * pA[ 99 ] + pA[ 25 ] * pA[ 100 ] + pA[ 31 ] * pA[ 101 ];
		pA[ 242 ] = pA[ 2 ] * pA[ 96 ] + pA[ 8 ] * pA[ 97 ] + pA[ 14 ] * pA[ 98 ] + pA[ 20 ] * pA[ 99 ] + pA[ 26 ] * pA[ 100 ] + pA[ 32 ] * pA[ 101 ];
		pA[ 243 ] = pA[ 3 ] * pA[ 96 ] + pA[ 9 ] * pA[ 97 ] + pA[ 15 ] * pA[ 98 ] + pA[ 21 ] * pA[ 99 ] + pA[ 27 ] * pA[ 100 ] + pA[ 33 ] * pA[ 101 ];
		pA[ 244 ] = pA[ 4 ] * pA[ 96 ] + pA[ 10 ] * pA[ 97 ] + pA[ 16 ] * pA[ 98 ] + pA[ 22 ] * pA[ 99 ] + pA[ 28 ] * pA[ 100 ] + pA[ 34 ] * pA[ 101 ];
		pA[ 245 ] = pA[ 5 ] * pA[ 96 ] + pA[ 11 ] * pA[ 97 ] + pA[ 17 ] * pA[ 98 ] + pA[ 23 ] * pA[ 99 ] + pA[ 29 ] * pA[ 100 ] + pA[ 35 ] * pA[ 101 ];
	}
	{
		pA[ 246 ] = pA[ 0 ] * pA[ 102 ] + pA[ 6 ] * pA[ 103 ] + pA[ 12 ] * pA[ 104 ] + pA[ 18 ] * pA[ 105 ] + pA[ 24 ] * pA[ 106 ] + pA[ 30 ] * pA[ 107 ];
		pA[ 247 ] = pA[ 1 ] * pA[ 102 ] + pA[ 7 ] * pA[ 103 ] + pA[ 13 ] * pA[ 104 ] + pA[ 19 ] * pA[ 105 ] + pA[ 25 ] * pA[ 106 ] + pA[ 31 ] * pA[ 107 ];
		pA[ 248 ] = pA[ 2 ] * pA[ 102 ] + pA[ 8 ] * pA[ 103 ] + pA[ 14 ] * pA[ 104 ] + pA[ 20 ] * pA[ 105 ] + pA[ 26 ] * pA[ 106 ] + pA[ 32 ] * pA[ 107 ];
		pA[ 249 ] = pA[ 3 ] * pA[ 102 ] + pA[ 9 ] * pA[ 103 ] + pA[ 15 ] * pA[ 104 ] + pA[ 21 ] * pA[ 105 ] + pA[ 27 ] * pA[ 106 ] + pA[ 33 ] * pA[ 107 ];
		pA[ 250 ] = pA[ 4 ] * pA[ 102 ] + pA[ 10 ] * pA[ 103 ] + pA[ 16 ] * pA[ 104 ] + pA[ 22 ] * pA[ 105 ] + pA[ 28 ] * pA[ 106 ] + pA[ 34 ] * pA[ 107 ];
		pA[ 251 ] = pA[ 5 ] * pA[ 102 ] + pA[ 11 ] * pA[ 103 ] + pA[ 17 ] * pA[ 104 ] + pA[ 23 ] * pA[ 105 ] + pA[ 29 ] * pA[ 106 ] + pA[ 35 ] * pA[ 107 ];
	}
	{
		pA[ 252 ] = pA[ 0 ] * pA[ 108 ] + pA[ 6 ] * pA[ 109 ] + pA[ 12 ] * pA[ 110 ] + pA[ 18 ] * pA[ 111 ] + pA[ 24 ] * pA[ 112 ] + pA[ 30 ] * pA[ 113 ];
		pA[ 253 ] = pA[ 1 ] * pA[ 108 ] + pA[ 7 ] * pA[ 109 ] + pA[ 13 ] * pA[ 110 ] + pA[ 19 ] * pA[ 111 ] + pA[ 25 ] * pA[ 112 ] + pA[ 31 ] * pA[ 113 ];
		pA[ 254 ] = pA[ 2 ] * pA[ 108 ] + pA[ 8 ] * pA[ 109 ] + pA[ 14 ] * pA[ 110 ] + pA[ 20 ] * pA[ 111 ] + pA[ 26 ] * pA[ 112 ] + pA[ 32 ] * pA[ 113 ];
		pA[ 255 ] = pA[ 3 ] * pA[ 108 ] + pA[ 9 ] * pA[ 109 ] + pA[ 15 ] * pA[ 110 ] + pA[ 21 ] * pA[ 111 ] + pA[ 27 ] * pA[ 112 ] + pA[ 33 ] * pA[ 113 ];
		pA[ 256 ] = pA[ 4 ] * pA[ 108 ] + pA[ 10 ] * pA[ 109 ] + pA[ 16 ] * pA[ 110 ] + pA[ 22 ] * pA[ 111 ] + pA[ 28 ] * pA[ 112 ] + pA[ 34 ] * pA[ 113 ];
		pA[ 257 ] = pA[ 5 ] * pA[ 108 ] + pA[ 11 ] * pA[ 109 ] + pA[ 17 ] * pA[ 110 ] + pA[ 23 ] * pA[ 111 ] + pA[ 29 ] * pA[ 112 ] + pA[ 35 ] * pA[ 113 ];
	}
	{
		pA[ 258 ] = pA[ 0 ] * pA[ 114 ] + pA[ 6 ] * pA[ 115 ] + pA[ 12 ] * pA[ 116 ] + pA[ 18 ] * pA[ 117 ] + pA[ 24 ] * pA[ 118 ] + pA[ 30 ] * pA[ 119 ];
		pA[ 259 ] = pA[ 1 ] * pA[ 114 ] + pA[ 7 ] * pA[ 115 ] + pA[ 13 ] * pA[ 116 ] + pA[ 19 ] * pA[ 117 ] + pA[ 25 ] * pA[ 118 ] + pA[ 31 ] * pA[ 119 ];
		pA[ 260 ] = pA[ 2 ] * pA[ 114 ] + pA[ 8 ] * pA[ 115 ] + pA[ 14 ] * pA[ 116 ] + pA[ 20 ] * pA[ 117 ] + pA[ 26 ] * pA[ 118 ] + pA[ 32 ] * pA[ 119 ];
		pA[ 261 ] = pA[ 3 ] * pA[ 114 ] + pA[ 9 ] * pA[ 115 ] + pA[ 15 ] * pA[ 116 ] + pA[ 21 ] * pA[ 117 ] + pA[ 27 ] * pA[ 118 ] + pA[ 33 ] * pA[ 119 ];
		pA[ 262 ] = pA[ 4 ] * pA[ 114 ] + pA[ 10 ] * pA[ 115 ] + pA[ 16 ] * pA[ 116 ] + pA[ 22 ] * pA[ 117 ] + pA[ 28 ] * pA[ 118 ] + pA[ 34 ] * pA[ 119 ];
		pA[ 263 ] = pA[ 5 ] * pA[ 114 ] + pA[ 11 ] * pA[ 115 ] + pA[ 17 ] * pA[ 116 ] + pA[ 23 ] * pA[ 117 ] + pA[ 29 ] * pA[ 118 ] + pA[ 35 ] * pA[ 119 ];
	}
	{
		pA[ 264 ] = pA[ 0 ] * pA[ 120 ] + pA[ 6 ] * pA[ 121 ] + pA[ 12 ] * pA[ 122 ] + pA[ 18 ] * pA[ 123 ] + pA[ 24 ] * pA[ 124 ] + pA[ 30 ] * pA[ 125 ];
		pA[ 265 ] = pA[ 1 ] * pA[ 120 ] + pA[ 7 ] * pA[ 121 ] + pA[ 13 ] * pA[ 122 ] + pA[ 19 ] * pA[ 123 ] + pA[ 25 ] * pA[ 124 ] + pA[ 31 ] * pA[ 125 ];
		pA[ 266 ] = pA[ 2 ] * pA[ 120 ] + pA[ 8 ] * pA[ 121 ] + pA[ 14 ] * pA[ 122 ] + pA[ 20 ] * pA[ 123 ] + pA[ 26 ] * pA[ 124 ] + pA[ 32 ] * pA[ 125 ];
		pA[ 267 ] = pA[ 3 ] * pA[ 120 ] + pA[ 9 ] * pA[ 121 ] + pA[ 15 ] * pA[ 122 ] + pA[ 21 ] * pA[ 123 ] + pA[ 27 ] * pA[ 124 ] + pA[ 33 ] * pA[ 125 ];
		pA[ 268 ] = pA[ 4 ] * pA[ 120 ] + pA[ 10 ] * pA[ 121 ] + pA[ 16 ] * pA[ 122 ] + pA[ 22 ] * pA[ 123 ] + pA[ 28 ] * pA[ 124 ] + pA[ 34 ] * pA[ 125 ];
		pA[ 269 ] = pA[ 5 ] * pA[ 120 ] + pA[ 11 ] * pA[ 121 ] + pA[ 17 ] * pA[ 122 ] + pA[ 23 ] * pA[ 123 ] + pA[ 29 ] * pA[ 124 ] + pA[ 35 ] * pA[ 125 ];
	}
	{
		pA[ 270 ] = pA[ 0 ] * pA[ 126 ] + pA[ 6 ] * pA[ 127 ] + pA[ 12 ] * pA[ 128 ] + pA[ 18 ] * pA[ 129 ] + pA[ 24 ] * pA[ 130 ] + pA[ 30 ] * pA[ 131 ];
		pA[ 271 ] = pA[ 1 ] * pA[ 126 ] + pA[ 7 ] * pA[ 127 ] + pA[ 13 ] * pA[ 128 ] + pA[ 19 ] * pA[ 129 ] + pA[ 25 ] * pA[ 130 ] + pA[ 31 ] * pA[ 131 ];
		pA[ 272 ] = pA[ 2 ] * pA[ 126 ] + pA[ 8 ] * pA[ 127 ] + pA[ 14 ] * pA[ 128 ] + pA[ 20 ] * pA[ 129 ] + pA[ 26 ] * pA[ 130 ] + pA[ 32 ] * pA[ 131 ];
		pA[ 273 ] = pA[ 3 ] * pA[ 126 ] + pA[ 9 ] * pA[ 127 ] + pA[ 15 ] * pA[ 128 ] + pA[ 21 ] * pA[ 129 ] + pA[ 27 ] * pA[ 130 ] + pA[ 33 ] * pA[ 131 ];
		pA[ 274 ] = pA[ 4 ] * pA[ 126 ] + pA[ 10 ] * pA[ 127 ] + pA[ 16 ] * pA[ 128 ] + pA[ 22 ] * pA[ 129 ] + pA[ 28 ] * pA[ 130 ] + pA[ 34 ] * pA[ 131 ];
		pA[ 275 ] = pA[ 5 ] * pA[ 126 ] + pA[ 11 ] * pA[ 127 ] + pA[ 17 ] * pA[ 128 ] + pA[ 23 ] * pA[ 129 ] + pA[ 29 ] * pA[ 130 ] + pA[ 35 ] * pA[ 131 ];
	}
	{
		pA[ 276 ] = pA[ 0 ] * pA[ 132 ] + pA[ 6 ] * pA[ 133 ] + pA[ 12 ] * pA[ 134 ] + pA[ 18 ] * pA[ 135 ] + pA[ 24 ] * pA[ 136 ] + pA[ 30 ] * pA[ 137 ];
		pA[ 277 ] = pA[ 1 ] * pA[ 132 ] + pA[ 7 ] * pA[ 133 ] + pA[ 13 ] * pA[ 134 ] + pA[ 19 ] * pA[ 135 ] + pA[ 25 ] * pA[ 136 ] + pA[ 31 ] * pA[ 137 ];
		pA[ 278 ] = pA[ 2 ] * pA[ 132 ] + pA[ 8 ] * pA[ 133 ] + pA[ 14 ] * pA[ 134 ] + pA[ 20 ] * pA[ 135 ] + pA[ 26 ] * pA[ 136 ] + pA[ 32 ] * pA[ 137 ];
		pA[ 279 ] = pA[ 3 ] * pA[ 132 ] + pA[ 9 ] * pA[ 133 ] + pA[ 15 ] * pA[ 134 ] + pA[ 21 ] * pA[ 135 ] + pA[ 27 ] * pA[ 136 ] + pA[ 33 ] * pA[ 137 ];
		pA[ 280 ] = pA[ 4 ] * pA[ 132 ] + pA[ 10 ] * pA[ 133 ] + pA[ 16 ] * pA[ 134 ] + pA[ 22 ] * pA[ 135 ] + pA[ 28 ] * pA[ 136 ] + pA[ 34 ] * pA[ 137 ];
		pA[ 281 ] = pA[ 5 ] * pA[ 132 ] + pA[ 11 ] * pA[ 133 ] + pA[ 17 ] * pA[ 134 ] + pA[ 23 ] * pA[ 135 ] + pA[ 29 ] * pA[ 136 ] + pA[ 35 ] * pA[ 137 ];
	}
	{
		pA[ 282 ] = pA[ 0 ] * pA[ 138 ] + pA[ 6 ] * pA[ 139 ] + pA[ 12 ] * pA[ 140 ] + pA[ 18 ] * pA[ 141 ] + pA[ 24 ] * pA[ 142 ] + pA[ 30 ] * pA[ 143 ];
		pA[ 283 ] = pA[ 1 ] * pA[ 138 ] + pA[ 7 ] * pA[ 139 ] + pA[ 13 ] * pA[ 140 ] + pA[ 19 ] * pA[ 141 ] + pA[ 25 ] * pA[ 142 ] + pA[ 31 ] * pA[ 143 ];
		pA[ 284 ] = pA[ 2 ] * pA[ 138 ] + pA[ 8 ] * pA[ 139 ] + pA[ 14 ] * pA[ 140 ] + pA[ 20 ] * pA[ 141 ] + pA[ 26 ] * pA[ 142 ] + pA[ 32 ] * pA[ 143 ];
		pA[ 285 ] = pA[ 3 ] * pA[ 138 ] + pA[ 9 ] * pA[ 139 ] + pA[ 15 ] * pA[ 140 ] + pA[ 21 ] * pA[ 141 ] + pA[ 27 ] * pA[ 142 ] + pA[ 33 ] * pA[ 143 ];
		pA[ 286 ] = pA[ 4 ] * pA[ 138 ] + pA[ 10 ] * pA[ 139 ] + pA[ 16 ] * pA[ 140 ] + pA[ 22 ] * pA[ 141 ] + pA[ 28 ] * pA[ 142 ] + pA[ 34 ] * pA[ 143 ];
		pA[ 287 ] = pA[ 5 ] * pA[ 138 ] + pA[ 11 ] * pA[ 139 ] + pA[ 17 ] * pA[ 140 ] + pA[ 23 ] * pA[ 141 ] + pA[ 29 ] * pA[ 142 ] + pA[ 35 ] * pA[ 143 ];
	}
	{
		pA[ 288 ] = pA[ 0 ] * pA[ 144 ] + pA[ 6 ] * pA[ 145 ] + pA[ 12 ] * pA[ 146 ] + pA[ 18 ] * pA[ 147 ] + pA[ 24 ] * pA[ 148 ] + pA[ 30 ] * pA[ 149 ];
		pA[ 289 ] = pA[ 1 ] * pA[ 144 ] + pA[ 7 ] * pA[ 145 ] + pA[ 13 ] * pA[ 146 ] + pA[ 19 ] * pA[ 147 ] + pA[ 25 ] * pA[ 148 ] + pA[ 31 ] * pA[ 149 ];
		pA[ 290 ] = pA[ 2 ] * pA[ 144 ] + pA[ 8 ] * pA[ 145 ] + pA[ 14 ] * pA[ 146 ] + pA[ 20 ] * pA[ 147 ] + pA[ 26 ] * pA[ 148 ] + pA[ 32 ] * pA[ 149 ];
		pA[ 291 ] = pA[ 3 ] * pA[ 144 ] + pA[ 9 ] * pA[ 145 ] + pA[ 15 ] * pA[ 146 ] + pA[ 21 ] * pA[ 147 ] + pA[ 27 ] * pA[ 148 ] + pA[ 33 ] * pA[ 149 ];
		pA[ 292 ] = pA[ 4 ] * pA[ 144 ] + pA[ 10 ] * pA[ 145 ] + pA[ 16 ] * pA[ 146 ] + pA[ 22 ] * pA[ 147 ] + pA[ 28 ] * pA[ 148 ] + pA[ 34 ] * pA[ 149 ];
		pA[ 293 ] = pA[ 5 ] * pA[ 144 ] + pA[ 11 ] * pA[ 145 ] + pA[ 17 ] * pA[ 146 ] + pA[ 23 ] * pA[ 147 ] + pA[ 29 ] * pA[ 148 ] + pA[ 35 ] * pA[ 149 ];
	}
	{
		pA[ 294 ] = pA[ 0 ] * pA[ 150 ] + pA[ 6 ] * pA[ 151 ] + pA[ 12 ] * pA[ 152 ] + pA[ 18 ] * pA[ 153 ] + pA[ 24 ] * pA[ 154 ] + pA[ 30 ] * pA[ 155 ];
		pA[ 295 ] = pA[ 1 ] * pA[ 150 ] + pA[ 7 ] * pA[ 151 ] + pA[ 13 ] * pA[ 152 ] + pA[ 19 ] * pA[ 153 ] + pA[ 25 ] * pA[ 154 ] + pA[ 31 ] * pA[ 155 ];
		pA[ 296 ] = pA[ 2 ] * pA[ 150 ] + pA[ 8 ] * pA[ 151 ] + pA[ 14 ] * pA[ 152 ] + pA[ 20 ] * pA[ 153 ] + pA[ 26 ] * pA[ 154 ] + pA[ 32 ] * pA[ 155 ];
		pA[ 297 ] = pA[ 3 ] * pA[ 150 ] + pA[ 9 ] * pA[ 151 ] + pA[ 15 ] * pA[ 152 ] + pA[ 21 ] * pA[ 153 ] + pA[ 27 ] * pA[ 154 ] + pA[ 33 ] * pA[ 155 ];
		pA[ 298 ] = pA[ 4 ] * pA[ 150 ] + pA[ 10 ] * pA[ 151 ] + pA[ 16 ] * pA[ 152 ] + pA[ 22 ] * pA[ 153 ] + pA[ 28 ] * pA[ 154 ] + pA[ 34 ] * pA[ 155 ];
		pA[ 299 ] = pA[ 5 ] * pA[ 150 ] + pA[ 11 ] * pA[ 151 ] + pA[ 17 ] * pA[ 152 ] + pA[ 23 ] * pA[ 153 ] + pA[ 29 ] * pA[ 154 ] + pA[ 35 ] * pA[ 155 ];
	}
	{
		pA[ 300 ] = pA[ 0 ] * pA[ 156 ] + pA[ 6 ] * pA[ 157 ] + pA[ 12 ] * pA[ 158 ] + pA[ 18 ] * pA[ 159 ] + pA[ 24 ] * pA[ 160 ] + pA[ 30 ] * pA[ 161 ];
		pA[ 301 ] = pA[ 1 ] * pA[ 156 ] + pA[ 7 ] * pA[ 157 ] + pA[ 13 ] * pA[ 158 ] + pA[ 19 ] * pA[ 159 ] + pA[ 25 ] * pA[ 160 ] + pA[ 31 ] * pA[ 161 ];
		pA[ 302 ] = pA[ 2 ] * pA[ 156 ] + pA[ 8 ] * pA[ 157 ] + pA[ 14 ] * pA[ 158 ] + pA[ 20 ] * pA[ 159 ] + pA[ 26 ] * pA[ 160 ] + pA[ 32 ] * pA[ 161 ];
		pA[ 303 ] = pA[ 3 ] * pA[ 156 ] + pA[ 9 ] * pA[ 157 ] + pA[ 15 ] * pA[ 158 ] + pA[ 21 ] * pA[ 159 ] + pA[ 27 ] * pA[ 160 ] + pA[ 33 ] * pA[ 161 ];
		pA[ 304 ] = pA[ 4 ] * pA[ 156 ] + pA[ 10 ] * pA[ 157 ] + pA[ 16 ] * pA[ 158 ] + pA[ 22 ] * pA[ 159 ] + pA[ 28 ] * pA[ 160 ] + pA[ 34 ] * pA[ 161 ];
		pA[ 305 ] = pA[ 5 ] * pA[ 156 ] + pA[ 11 ] * pA[ 157 ] + pA[ 17 ] * pA[ 158 ] + pA[ 23 ] * pA[ 159 ] + pA[ 29 ] * pA[ 160 ] + pA[ 35 ] * pA[ 161 ];
	}
	{
		pA[ 306 ] = pA[ 0 ] * pA[ 162 ] + pA[ 6 ] * pA[ 163 ] + pA[ 12 ] * pA[ 164 ] + pA[ 18 ] * pA[ 165 ] + pA[ 24 ] * pA[ 166 ] + pA[ 30 ] * pA[ 167 ];
		pA[ 307 ] = pA[ 1 ] * pA[ 162 ] + pA[ 7 ] * pA[ 163 ] + pA[ 13 ] * pA[ 164 ] + pA[ 19 ] * pA[ 165 ] + pA[ 25 ] * pA[ 166 ] + pA[ 31 ] * pA[ 167 ];
		pA[ 308 ] = pA[ 2 ] * pA[ 162 ] + pA[ 8 ] * pA[ 163 ] + pA[ 14 ] * pA[ 164 ] + pA[ 20 ] * pA[ 165 ] + pA[ 26 ] * pA[ 166 ] + pA[ 32 ] * pA[ 167 ];
		pA[ 309 ] = pA[ 3 ] * pA[ 162 ] + pA[ 9 ] * pA[ 163 ] + pA[ 15 ] * pA[ 164 ] + pA[ 21 ] * pA[ 165 ] + pA[ 27 ] * pA[ 166 ] + pA[ 33 ] * pA[ 167 ];
		pA[ 310 ] = pA[ 4 ] * pA[ 162 ] + pA[ 10 ] * pA[ 163 ] + pA[ 16 ] * pA[ 164 ] + pA[ 22 ] * pA[ 165 ] + pA[ 28 ] * pA[ 166 ] + pA[ 34 ] * pA[ 167 ];
		pA[ 311 ] = pA[ 5 ] * pA[ 162 ] + pA[ 11 ] * pA[ 163 ] + pA[ 17 ] * pA[ 164 ] + pA[ 23 ] * pA[ 165 ] + pA[ 29 ] * pA[ 166 ] + pA[ 35 ] * pA[ 167 ];
	}
	{
		pA[ 312 ] = pA[ 0 ] * pA[ 168 ] + pA[ 6 ] * pA[ 169 ] + pA[ 12 ] * pA[ 170 ] + pA[ 18 ] * pA[ 171 ] + pA[ 24 ] * pA[ 172 ] + pA[ 30 ] * pA[ 173 ];
		pA[ 313 ] = pA[ 1 ] * pA[ 168 ] + pA[ 7 ] * pA[ 169 ] + pA[ 13 ] * pA[ 170 ] + pA[ 19 ] * pA[ 171 ] + pA[ 25 ] * pA[ 172 ] + pA[ 31 ] * pA[ 173 ];
		pA[ 314 ] = pA[ 2 ] * pA[ 168 ] + pA[ 8 ] * pA[ 169 ] + pA[ 14 ] * pA[ 170 ] + pA[ 20 ] * pA[ 171 ] + pA[ 26 ] * pA[ 172 ] + pA[ 32 ] * pA[ 173 ];
		pA[ 315 ] = pA[ 3 ] * pA[ 168 ] + pA[ 9 ] * pA[ 169 ] + pA[ 15 ] * pA[ 170 ] + pA[ 21 ] * pA[ 171 ] + pA[ 27 ] * pA[ 172 ] + pA[ 33 ] * pA[ 173 ];
		pA[ 316 ] = pA[ 4 ] * pA[ 168 ] + pA[ 10 ] * pA[ 169 ] + pA[ 16 ] * pA[ 170 ] + pA[ 22 ] * pA[ 171 ] + pA[ 28 ] * pA[ 172 ] + pA[ 34 ] * pA[ 173 ];
		pA[ 317 ] = pA[ 5 ] * pA[ 168 ] + pA[ 11 ] * pA[ 169 ] + pA[ 17 ] * pA[ 170 ] + pA[ 23 ] * pA[ 171 ] + pA[ 29 ] * pA[ 172 ] + pA[ 35 ] * pA[ 173 ];
	}
	{
		pA[ 318 ] = pA[ 0 ] * pA[ 174 ] + pA[ 6 ] * pA[ 175 ] + pA[ 12 ] * pA[ 176 ] + pA[ 18 ] * pA[ 177 ] + pA[ 24 ] * pA[ 178 ] + pA[ 30 ] * pA[ 179 ];
		pA[ 319 ] = pA[ 1 ] * pA[ 174 ] + pA[ 7 ] * pA[ 175 ] + pA[ 13 ] * pA[ 176 ] + pA[ 19 ] * pA[ 177 ] + pA[ 25 ] * pA[ 178 ] + pA[ 31 ] * pA[ 179 ];
		pA[ 320 ] = pA[ 2 ] * pA[ 174 ] + pA[ 8 ] * pA[ 175 ] + pA[ 14 ] * pA[ 176 ] + pA[ 20 ] * pA[ 177 ] + pA[ 26 ] * pA[ 178 ] + pA[ 32 ] * pA[ 179 ];
		pA[ 321 ] = pA[ 3 ] * pA[ 174 ] + pA[ 9 ] * pA[ 175 ] + pA[ 15 ] * pA[ 176 ] + pA[ 21 ] * pA[ 177 ] + pA[ 27 ] * pA[ 178 ] + pA[ 33 ] * pA[ 179 ];
		pA[ 322 ] = pA[ 4 ] * pA[ 174 ] + pA[ 10 ] * pA[ 175 ] + pA[ 16 ] * pA[ 176 ] + pA[ 22 ] * pA[ 177 ] + pA[ 28 ] * pA[ 178 ] + pA[ 34 ] * pA[ 179 ];
		pA[ 323 ] = pA[ 5 ] * pA[ 174 ] + pA[ 11 ] * pA[ 175 ] + pA[ 17 ] * pA[ 176 ] + pA[ 23 ] * pA[ 177 ] + pA[ 29 ] * pA[ 178 ] + pA[ 35 ] * pA[ 179 ];
	}
	return	true;
}
(b)の行列掛け算の実装
inline bool	mmultABX_b( const double* pA, const double* pB, double* pX )
{
	{
		pX[ 0 ] = pA[ 0 ] * pB[ 0 ] + pA[ 6 ] * pB[ 1 ] + pA[ 12 ] * pB[ 2 ] + pA[ 18 ] * pB[ 3 ] + pA[ 24 ] * pB[ 4 ] + pA[ 30 ] * pB[ 5 ];
		pX[ 1 ] = pA[ 1 ] * pB[ 0 ] + pA[ 7 ] * pB[ 1 ] + pA[ 13 ] * pB[ 2 ] + pA[ 19 ] * pB[ 3 ] + pA[ 25 ] * pB[ 4 ] + pA[ 31 ] * pB[ 5 ];
		pX[ 2 ] = pA[ 2 ] * pB[ 0 ] + pA[ 8 ] * pB[ 1 ] + pA[ 14 ] * pB[ 2 ] + pA[ 20 ] * pB[ 3 ] + pA[ 26 ] * pB[ 4 ] + pA[ 32 ] * pB[ 5 ];
		pX[ 3 ] = pA[ 3 ] * pB[ 0 ] + pA[ 9 ] * pB[ 1 ] + pA[ 15 ] * pB[ 2 ] + pA[ 21 ] * pB[ 3 ] + pA[ 27 ] * pB[ 4 ] + pA[ 33 ] * pB[ 5 ];
		pX[ 4 ] = pA[ 4 ] * pB[ 0 ] + pA[ 10 ] * pB[ 1 ] + pA[ 16 ] * pB[ 2 ] + pA[ 22 ] * pB[ 3 ] + pA[ 28 ] * pB[ 4 ] + pA[ 34 ] * pB[ 5 ];
		pX[ 5 ] = pA[ 5 ] * pB[ 0 ] + pA[ 11 ] * pB[ 1 ] + pA[ 17 ] * pB[ 2 ] + pA[ 23 ] * pB[ 3 ] + pA[ 29 ] * pB[ 4 ] + pA[ 35 ] * pB[ 5 ];
	}
	{
		pX[ 6 ] = pA[ 0 ] * pB[ 6 ] + pA[ 6 ] * pB[ 7 ] + pA[ 12 ] * pB[ 8 ] + pA[ 18 ] * pB[ 9 ] + pA[ 24 ] * pB[ 10 ] + pA[ 30 ] * pB[ 11 ];
		pX[ 7 ] = pA[ 1 ] * pB[ 6 ] + pA[ 7 ] * pB[ 7 ] + pA[ 13 ] * pB[ 8 ] + pA[ 19 ] * pB[ 9 ] + pA[ 25 ] * pB[ 10 ] + pA[ 31 ] * pB[ 11 ];
		pX[ 8 ] = pA[ 2 ] * pB[ 6 ] + pA[ 8 ] * pB[ 7 ] + pA[ 14 ] * pB[ 8 ] + pA[ 20 ] * pB[ 9 ] + pA[ 26 ] * pB[ 10 ] + pA[ 32 ] * pB[ 11 ];
		pX[ 9 ] = pA[ 3 ] * pB[ 6 ] + pA[ 9 ] * pB[ 7 ] + pA[ 15 ] * pB[ 8 ] + pA[ 21 ] * pB[ 9 ] + pA[ 27 ] * pB[ 10 ] + pA[ 33 ] * pB[ 11 ];
		pX[ 10 ] = pA[ 4 ] * pB[ 6 ] + pA[ 10 ] * pB[ 7 ] + pA[ 16 ] * pB[ 8 ] + pA[ 22 ] * pB[ 9 ] + pA[ 28 ] * pB[ 10 ] + pA[ 34 ] * pB[ 11 ];
		pX[ 11 ] = pA[ 5 ] * pB[ 6 ] + pA[ 11 ] * pB[ 7 ] + pA[ 17 ] * pB[ 8 ] + pA[ 23 ] * pB[ 9 ] + pA[ 29 ] * pB[ 10 ] + pA[ 35 ] * pB[ 11 ];
	}
	{
		pX[ 12 ] = pA[ 0 ] * pB[ 12 ] + pA[ 6 ] * pB[ 13 ] + pA[ 12 ] * pB[ 14 ] + pA[ 18 ] * pB[ 15 ] + pA[ 24 ] * pB[ 16 ] + pA[ 30 ] * pB[ 17 ];
		pX[ 13 ] = pA[ 1 ] * pB[ 12 ] + pA[ 7 ] * pB[ 13 ] + pA[ 13 ] * pB[ 14 ] + pA[ 19 ] * pB[ 15 ] + pA[ 25 ] * pB[ 16 ] + pA[ 31 ] * pB[ 17 ];
		pX[ 14 ] = pA[ 2 ] * pB[ 12 ] + pA[ 8 ] * pB[ 13 ] + pA[ 14 ] * pB[ 14 ] + pA[ 20 ] * pB[ 15 ] + pA[ 26 ] * pB[ 16 ] + pA[ 32 ] * pB[ 17 ];
		pX[ 15 ] = pA[ 3 ] * pB[ 12 ] + pA[ 9 ] * pB[ 13 ] + pA[ 15 ] * pB[ 14 ] + pA[ 21 ] * pB[ 15 ] + pA[ 27 ] * pB[ 16 ] + pA[ 33 ] * pB[ 17 ];
		pX[ 16 ] = pA[ 4 ] * pB[ 12 ] + pA[ 10 ] * pB[ 13 ] + pA[ 16 ] * pB[ 14 ] + pA[ 22 ] * pB[ 15 ] + pA[ 28 ] * pB[ 16 ] + pA[ 34 ] * pB[ 17 ];
		pX[ 17 ] = pA[ 5 ] * pB[ 12 ] + pA[ 11 ] * pB[ 13 ] + pA[ 17 ] * pB[ 14 ] + pA[ 23 ] * pB[ 15 ] + pA[ 29 ] * pB[ 16 ] + pA[ 35 ] * pB[ 17 ];
	}
	{
		pX[ 18 ] = pA[ 0 ] * pB[ 18 ] + pA[ 6 ] * pB[ 19 ] + pA[ 12 ] * pB[ 20 ] + pA[ 18 ] * pB[ 21 ] + pA[ 24 ] * pB[ 22 ] + pA[ 30 ] * pB[ 23 ];
		pX[ 19 ] = pA[ 1 ] * pB[ 18 ] + pA[ 7 ] * pB[ 19 ] + pA[ 13 ] * pB[ 20 ] + pA[ 19 ] * pB[ 21 ] + pA[ 25 ] * pB[ 22 ] + pA[ 31 ] * pB[ 23 ];
		pX[ 20 ] = pA[ 2 ] * pB[ 18 ] + pA[ 8 ] * pB[ 19 ] + pA[ 14 ] * pB[ 20 ] + pA[ 20 ] * pB[ 21 ] + pA[ 26 ] * pB[ 22 ] + pA[ 32 ] * pB[ 23 ];
		pX[ 21 ] = pA[ 3 ] * pB[ 18 ] + pA[ 9 ] * pB[ 19 ] + pA[ 15 ] * pB[ 20 ] + pA[ 21 ] * pB[ 21 ] + pA[ 27 ] * pB[ 22 ] + pA[ 33 ] * pB[ 23 ];
		pX[ 22 ] = pA[ 4 ] * pB[ 18 ] + pA[ 10 ] * pB[ 19 ] + pA[ 16 ] * pB[ 20 ] + pA[ 22 ] * pB[ 21 ] + pA[ 28 ] * pB[ 22 ] + pA[ 34 ] * pB[ 23 ];
		pX[ 23 ] = pA[ 5 ] * pB[ 18 ] + pA[ 11 ] * pB[ 19 ] + pA[ 17 ] * pB[ 20 ] + pA[ 23 ] * pB[ 21 ] + pA[ 29 ] * pB[ 22 ] + pA[ 35 ] * pB[ 23 ];
	}
	{
		pX[ 24 ] = pA[ 0 ] * pB[ 24 ] + pA[ 6 ] * pB[ 25 ] + pA[ 12 ] * pB[ 26 ] + pA[ 18 ] * pB[ 27 ] + pA[ 24 ] * pB[ 28 ] + pA[ 30 ] * pB[ 29 ];
		pX[ 25 ] = pA[ 1 ] * pB[ 24 ] + pA[ 7 ] * pB[ 25 ] + pA[ 13 ] * pB[ 26 ] + pA[ 19 ] * pB[ 27 ] + pA[ 25 ] * pB[ 28 ] + pA[ 31 ] * pB[ 29 ];
		pX[ 26 ] = pA[ 2 ] * pB[ 24 ] + pA[ 8 ] * pB[ 25 ] + pA[ 14 ] * pB[ 26 ] + pA[ 20 ] * pB[ 27 ] + pA[ 26 ] * pB[ 28 ] + pA[ 32 ] * pB[ 29 ];
		pX[ 27 ] = pA[ 3 ] * pB[ 24 ] + pA[ 9 ] * pB[ 25 ] + pA[ 15 ] * pB[ 26 ] + pA[ 21 ] * pB[ 27 ] + pA[ 27 ] * pB[ 28 ] + pA[ 33 ] * pB[ 29 ];
		pX[ 28 ] = pA[ 4 ] * pB[ 24 ] + pA[ 10 ] * pB[ 25 ] + pA[ 16 ] * pB[ 26 ] + pA[ 22 ] * pB[ 27 ] + pA[ 28 ] * pB[ 28 ] + pA[ 34 ] * pB[ 29 ];
		pX[ 29 ] = pA[ 5 ] * pB[ 24 ] + pA[ 11 ] * pB[ 25 ] + pA[ 17 ] * pB[ 26 ] + pA[ 23 ] * pB[ 27 ] + pA[ 29 ] * pB[ 28 ] + pA[ 35 ] * pB[ 29 ];
	}
	{
		pX[ 30 ] = pA[ 0 ] * pB[ 30 ] + pA[ 6 ] * pB[ 31 ] + pA[ 12 ] * pB[ 32 ] + pA[ 18 ] * pB[ 33 ] + pA[ 24 ] * pB[ 34 ] + pA[ 30 ] * pB[ 35 ];
		pX[ 31 ] = pA[ 1 ] * pB[ 30 ] + pA[ 7 ] * pB[ 31 ] + pA[ 13 ] * pB[ 32 ] + pA[ 19 ] * pB[ 33 ] + pA[ 25 ] * pB[ 34 ] + pA[ 31 ] * pB[ 35 ];
		pX[ 32 ] = pA[ 2 ] * pB[ 30 ] + pA[ 8 ] * pB[ 31 ] + pA[ 14 ] * pB[ 32 ] + pA[ 20 ] * pB[ 33 ] + pA[ 26 ] * pB[ 34 ] + pA[ 32 ] * pB[ 35 ];
		pX[ 33 ] = pA[ 3 ] * pB[ 30 ] + pA[ 9 ] * pB[ 31 ] + pA[ 15 ] * pB[ 32 ] + pA[ 21 ] * pB[ 33 ] + pA[ 27 ] * pB[ 34 ] + pA[ 33 ] * pB[ 35 ];
		pX[ 34 ] = pA[ 4 ] * pB[ 30 ] + pA[ 10 ] * pB[ 31 ] + pA[ 16 ] * pB[ 32 ] + pA[ 22 ] * pB[ 33 ] + pA[ 28 ] * pB[ 34 ] + pA[ 34 ] * pB[ 35 ];
		pX[ 35 ] = pA[ 5 ] * pB[ 30 ] + pA[ 11 ] * pB[ 31 ] + pA[ 17 ] * pB[ 32 ] + pA[ 23 ] * pB[ 33 ] + pA[ 29 ] * pB[ 34 ] + pA[ 35 ] * pB[ 35 ];
	}
	{
		pX[ 36 ] = pA[ 0 ] * pB[ 36 ] + pA[ 6 ] * pB[ 37 ] + pA[ 12 ] * pB[ 38 ] + pA[ 18 ] * pB[ 39 ] + pA[ 24 ] * pB[ 40 ] + pA[ 30 ] * pB[ 41 ];
		pX[ 37 ] = pA[ 1 ] * pB[ 36 ] + pA[ 7 ] * pB[ 37 ] + pA[ 13 ] * pB[ 38 ] + pA[ 19 ] * pB[ 39 ] + pA[ 25 ] * pB[ 40 ] + pA[ 31 ] * pB[ 41 ];
		pX[ 38 ] = pA[ 2 ] * pB[ 36 ] + pA[ 8 ] * pB[ 37 ] + pA[ 14 ] * pB[ 38 ] + pA[ 20 ] * pB[ 39 ] + pA[ 26 ] * pB[ 40 ] + pA[ 32 ] * pB[ 41 ];
		pX[ 39 ] = pA[ 3 ] * pB[ 36 ] + pA[ 9 ] * pB[ 37 ] + pA[ 15 ] * pB[ 38 ] + pA[ 21 ] * pB[ 39 ] + pA[ 27 ] * pB[ 40 ] + pA[ 33 ] * pB[ 41 ];
		pX[ 40 ] = pA[ 4 ] * pB[ 36 ] + pA[ 10 ] * pB[ 37 ] + pA[ 16 ] * pB[ 38 ] + pA[ 22 ] * pB[ 39 ] + pA[ 28 ] * pB[ 40 ] + pA[ 34 ] * pB[ 41 ];
		pX[ 41 ] = pA[ 5 ] * pB[ 36 ] + pA[ 11 ] * pB[ 37 ] + pA[ 17 ] * pB[ 38 ] + pA[ 23 ] * pB[ 39 ] + pA[ 29 ] * pB[ 40 ] + pA[ 35 ] * pB[ 41 ];
	}
	{
		pX[ 42 ] = pA[ 0 ] * pB[ 42 ] + pA[ 6 ] * pB[ 43 ] + pA[ 12 ] * pB[ 44 ] + pA[ 18 ] * pB[ 45 ] + pA[ 24 ] * pB[ 46 ] + pA[ 30 ] * pB[ 47 ];
		pX[ 43 ] = pA[ 1 ] * pB[ 42 ] + pA[ 7 ] * pB[ 43 ] + pA[ 13 ] * pB[ 44 ] + pA[ 19 ] * pB[ 45 ] + pA[ 25 ] * pB[ 46 ] + pA[ 31 ] * pB[ 47 ];
		pX[ 44 ] = pA[ 2 ] * pB[ 42 ] + pA[ 8 ] * pB[ 43 ] + pA[ 14 ] * pB[ 44 ] + pA[ 20 ] * pB[ 45 ] + pA[ 26 ] * pB[ 46 ] + pA[ 32 ] * pB[ 47 ];
		pX[ 45 ] = pA[ 3 ] * pB[ 42 ] + pA[ 9 ] * pB[ 43 ] + pA[ 15 ] * pB[ 44 ] + pA[ 21 ] * pB[ 45 ] + pA[ 27 ] * pB[ 46 ] + pA[ 33 ] * pB[ 47 ];
		pX[ 46 ] = pA[ 4 ] * pB[ 42 ] + pA[ 10 ] * pB[ 43 ] + pA[ 16 ] * pB[ 44 ] + pA[ 22 ] * pB[ 45 ] + pA[ 28 ] * pB[ 46 ] + pA[ 34 ] * pB[ 47 ];
		pX[ 47 ] = pA[ 5 ] * pB[ 42 ] + pA[ 11 ] * pB[ 43 ] + pA[ 17 ] * pB[ 44 ] + pA[ 23 ] * pB[ 45 ] + pA[ 29 ] * pB[ 46 ] + pA[ 35 ] * pB[ 47 ];
	}
	{
		pX[ 48 ] = pA[ 0 ] * pB[ 48 ] + pA[ 6 ] * pB[ 49 ] + pA[ 12 ] * pB[ 50 ] + pA[ 18 ] * pB[ 51 ] + pA[ 24 ] * pB[ 52 ] + pA[ 30 ] * pB[ 53 ];
		pX[ 49 ] = pA[ 1 ] * pB[ 48 ] + pA[ 7 ] * pB[ 49 ] + pA[ 13 ] * pB[ 50 ] + pA[ 19 ] * pB[ 51 ] + pA[ 25 ] * pB[ 52 ] + pA[ 31 ] * pB[ 53 ];
		pX[ 50 ] = pA[ 2 ] * pB[ 48 ] + pA[ 8 ] * pB[ 49 ] + pA[ 14 ] * pB[ 50 ] + pA[ 20 ] * pB[ 51 ] + pA[ 26 ] * pB[ 52 ] + pA[ 32 ] * pB[ 53 ];
		pX[ 51 ] = pA[ 3 ] * pB[ 48 ] + pA[ 9 ] * pB[ 49 ] + pA[ 15 ] * pB[ 50 ] + pA[ 21 ] * pB[ 51 ] + pA[ 27 ] * pB[ 52 ] + pA[ 33 ] * pB[ 53 ];
		pX[ 52 ] = pA[ 4 ] * pB[ 48 ] + pA[ 10 ] * pB[ 49 ] + pA[ 16 ] * pB[ 50 ] + pA[ 22 ] * pB[ 51 ] + pA[ 28 ] * pB[ 52 ] + pA[ 34 ] * pB[ 53 ];
		pX[ 53 ] = pA[ 5 ] * pB[ 48 ] + pA[ 11 ] * pB[ 49 ] + pA[ 17 ] * pB[ 50 ] + pA[ 23 ] * pB[ 51 ] + pA[ 29 ] * pB[ 52 ] + pA[ 35 ] * pB[ 53 ];
	}
	{
		pX[ 54 ] = pA[ 0 ] * pB[ 54 ] + pA[ 6 ] * pB[ 55 ] + pA[ 12 ] * pB[ 56 ] + pA[ 18 ] * pB[ 57 ] + pA[ 24 ] * pB[ 58 ] + pA[ 30 ] * pB[ 59 ];
		pX[ 55 ] = pA[ 1 ] * pB[ 54 ] + pA[ 7 ] * pB[ 55 ] + pA[ 13 ] * pB[ 56 ] + pA[ 19 ] * pB[ 57 ] + pA[ 25 ] * pB[ 58 ] + pA[ 31 ] * pB[ 59 ];
		pX[ 56 ] = pA[ 2 ] * pB[ 54 ] + pA[ 8 ] * pB[ 55 ] + pA[ 14 ] * pB[ 56 ] + pA[ 20 ] * pB[ 57 ] + pA[ 26 ] * pB[ 58 ] + pA[ 32 ] * pB[ 59 ];
		pX[ 57 ] = pA[ 3 ] * pB[ 54 ] + pA[ 9 ] * pB[ 55 ] + pA[ 15 ] * pB[ 56 ] + pA[ 21 ] * pB[ 57 ] + pA[ 27 ] * pB[ 58 ] + pA[ 33 ] * pB[ 59 ];
		pX[ 58 ] = pA[ 4 ] * pB[ 54 ] + pA[ 10 ] * pB[ 55 ] + pA[ 16 ] * pB[ 56 ] + pA[ 22 ] * pB[ 57 ] + pA[ 28 ] * pB[ 58 ] + pA[ 34 ] * pB[ 59 ];
		pX[ 59 ] = pA[ 5 ] * pB[ 54 ] + pA[ 11 ] * pB[ 55 ] + pA[ 17 ] * pB[ 56 ] + pA[ 23 ] * pB[ 57 ] + pA[ 29 ] * pB[ 58 ] + pA[ 35 ] * pB[ 59 ];
	}
	{
		pX[ 60 ] = pA[ 0 ] * pB[ 60 ] + pA[ 6 ] * pB[ 61 ] + pA[ 12 ] * pB[ 62 ] + pA[ 18 ] * pB[ 63 ] + pA[ 24 ] * pB[ 64 ] + pA[ 30 ] * pB[ 65 ];
		pX[ 61 ] = pA[ 1 ] * pB[ 60 ] + pA[ 7 ] * pB[ 61 ] + pA[ 13 ] * pB[ 62 ] + pA[ 19 ] * pB[ 63 ] + pA[ 25 ] * pB[ 64 ] + pA[ 31 ] * pB[ 65 ];
		pX[ 62 ] = pA[ 2 ] * pB[ 60 ] + pA[ 8 ] * pB[ 61 ] + pA[ 14 ] * pB[ 62 ] + pA[ 20 ] * pB[ 63 ] + pA[ 26 ] * pB[ 64 ] + pA[ 32 ] * pB[ 65 ];
		pX[ 63 ] = pA[ 3 ] * pB[ 60 ] + pA[ 9 ] * pB[ 61 ] + pA[ 15 ] * pB[ 62 ] + pA[ 21 ] * pB[ 63 ] + pA[ 27 ] * pB[ 64 ] + pA[ 33 ] * pB[ 65 ];
		pX[ 64 ] = pA[ 4 ] * pB[ 60 ] + pA[ 10 ] * pB[ 61 ] + pA[ 16 ] * pB[ 62 ] + pA[ 22 ] * pB[ 63 ] + pA[ 28 ] * pB[ 64 ] + pA[ 34 ] * pB[ 65 ];
		pX[ 65 ] = pA[ 5 ] * pB[ 60 ] + pA[ 11 ] * pB[ 61 ] + pA[ 17 ] * pB[ 62 ] + pA[ 23 ] * pB[ 63 ] + pA[ 29 ] * pB[ 64 ] + pA[ 35 ] * pB[ 65 ];
	}
	{
		pX[ 66 ] = pA[ 0 ] * pB[ 66 ] + pA[ 6 ] * pB[ 67 ] + pA[ 12 ] * pB[ 68 ] + pA[ 18 ] * pB[ 69 ] + pA[ 24 ] * pB[ 70 ] + pA[ 30 ] * pB[ 71 ];
		pX[ 67 ] = pA[ 1 ] * pB[ 66 ] + pA[ 7 ] * pB[ 67 ] + pA[ 13 ] * pB[ 68 ] + pA[ 19 ] * pB[ 69 ] + pA[ 25 ] * pB[ 70 ] + pA[ 31 ] * pB[ 71 ];
		pX[ 68 ] = pA[ 2 ] * pB[ 66 ] + pA[ 8 ] * pB[ 67 ] + pA[ 14 ] * pB[ 68 ] + pA[ 20 ] * pB[ 69 ] + pA[ 26 ] * pB[ 70 ] + pA[ 32 ] * pB[ 71 ];
		pX[ 69 ] = pA[ 3 ] * pB[ 66 ] + pA[ 9 ] * pB[ 67 ] + pA[ 15 ] * pB[ 68 ] + pA[ 21 ] * pB[ 69 ] + pA[ 27 ] * pB[ 70 ] + pA[ 33 ] * pB[ 71 ];
		pX[ 70 ] = pA[ 4 ] * pB[ 66 ] + pA[ 10 ] * pB[ 67 ] + pA[ 16 ] * pB[ 68 ] + pA[ 22 ] * pB[ 69 ] + pA[ 28 ] * pB[ 70 ] + pA[ 34 ] * pB[ 71 ];
		pX[ 71 ] = pA[ 5 ] * pB[ 66 ] + pA[ 11 ] * pB[ 67 ] + pA[ 17 ] * pB[ 68 ] + pA[ 23 ] * pB[ 69 ] + pA[ 29 ] * pB[ 70 ] + pA[ 35 ] * pB[ 71 ];
	}
	{
		pX[ 72 ] = pA[ 0 ] * pB[ 72 ] + pA[ 6 ] * pB[ 73 ] + pA[ 12 ] * pB[ 74 ] + pA[ 18 ] * pB[ 75 ] + pA[ 24 ] * pB[ 76 ] + pA[ 30 ] * pB[ 77 ];
		pX[ 73 ] = pA[ 1 ] * pB[ 72 ] + pA[ 7 ] * pB[ 73 ] + pA[ 13 ] * pB[ 74 ] + pA[ 19 ] * pB[ 75 ] + pA[ 25 ] * pB[ 76 ] + pA[ 31 ] * pB[ 77 ];
		pX[ 74 ] = pA[ 2 ] * pB[ 72 ] + pA[ 8 ] * pB[ 73 ] + pA[ 14 ] * pB[ 74 ] + pA[ 20 ] * pB[ 75 ] + pA[ 26 ] * pB[ 76 ] + pA[ 32 ] * pB[ 77 ];
		pX[ 75 ] = pA[ 3 ] * pB[ 72 ] + pA[ 9 ] * pB[ 73 ] + pA[ 15 ] * pB[ 74 ] + pA[ 21 ] * pB[ 75 ] + pA[ 27 ] * pB[ 76 ] + pA[ 33 ] * pB[ 77 ];
		pX[ 76 ] = pA[ 4 ] * pB[ 72 ] + pA[ 10 ] * pB[ 73 ] + pA[ 16 ] * pB[ 74 ] + pA[ 22 ] * pB[ 75 ] + pA[ 28 ] * pB[ 76 ] + pA[ 34 ] * pB[ 77 ];
		pX[ 77 ] = pA[ 5 ] * pB[ 72 ] + pA[ 11 ] * pB[ 73 ] + pA[ 17 ] * pB[ 74 ] + pA[ 23 ] * pB[ 75 ] + pA[ 29 ] * pB[ 76 ] + pA[ 35 ] * pB[ 77 ];
	}
	{
		pX[ 78 ] = pA[ 0 ] * pB[ 78 ] + pA[ 6 ] * pB[ 79 ] + pA[ 12 ] * pB[ 80 ] + pA[ 18 ] * pB[ 81 ] + pA[ 24 ] * pB[ 82 ] + pA[ 30 ] * pB[ 83 ];
		pX[ 79 ] = pA[ 1 ] * pB[ 78 ] + pA[ 7 ] * pB[ 79 ] + pA[ 13 ] * pB[ 80 ] + pA[ 19 ] * pB[ 81 ] + pA[ 25 ] * pB[ 82 ] + pA[ 31 ] * pB[ 83 ];
		pX[ 80 ] = pA[ 2 ] * pB[ 78 ] + pA[ 8 ] * pB[ 79 ] + pA[ 14 ] * pB[ 80 ] + pA[ 20 ] * pB[ 81 ] + pA[ 26 ] * pB[ 82 ] + pA[ 32 ] * pB[ 83 ];
		pX[ 81 ] = pA[ 3 ] * pB[ 78 ] + pA[ 9 ] * pB[ 79 ] + pA[ 15 ] * pB[ 80 ] + pA[ 21 ] * pB[ 81 ] + pA[ 27 ] * pB[ 82 ] + pA[ 33 ] * pB[ 83 ];
		pX[ 82 ] = pA[ 4 ] * pB[ 78 ] + pA[ 10 ] * pB[ 79 ] + pA[ 16 ] * pB[ 80 ] + pA[ 22 ] * pB[ 81 ] + pA[ 28 ] * pB[ 82 ] + pA[ 34 ] * pB[ 83 ];
		pX[ 83 ] = pA[ 5 ] * pB[ 78 ] + pA[ 11 ] * pB[ 79 ] + pA[ 17 ] * pB[ 80 ] + pA[ 23 ] * pB[ 81 ] + pA[ 29 ] * pB[ 82 ] + pA[ 35 ] * pB[ 83 ];
	}
	{
		pX[ 84 ] = pA[ 0 ] * pB[ 84 ] + pA[ 6 ] * pB[ 85 ] + pA[ 12 ] * pB[ 86 ] + pA[ 18 ] * pB[ 87 ] + pA[ 24 ] * pB[ 88 ] + pA[ 30 ] * pB[ 89 ];
		pX[ 85 ] = pA[ 1 ] * pB[ 84 ] + pA[ 7 ] * pB[ 85 ] + pA[ 13 ] * pB[ 86 ] + pA[ 19 ] * pB[ 87 ] + pA[ 25 ] * pB[ 88 ] + pA[ 31 ] * pB[ 89 ];
		pX[ 86 ] = pA[ 2 ] * pB[ 84 ] + pA[ 8 ] * pB[ 85 ] + pA[ 14 ] * pB[ 86 ] + pA[ 20 ] * pB[ 87 ] + pA[ 26 ] * pB[ 88 ] + pA[ 32 ] * pB[ 89 ];
		pX[ 87 ] = pA[ 3 ] * pB[ 84 ] + pA[ 9 ] * pB[ 85 ] + pA[ 15 ] * pB[ 86 ] + pA[ 21 ] * pB[ 87 ] + pA[ 27 ] * pB[ 88 ] + pA[ 33 ] * pB[ 89 ];
		pX[ 88 ] = pA[ 4 ] * pB[ 84 ] + pA[ 10 ] * pB[ 85 ] + pA[ 16 ] * pB[ 86 ] + pA[ 22 ] * pB[ 87 ] + pA[ 28 ] * pB[ 88 ] + pA[ 34 ] * pB[ 89 ];
		pX[ 89 ] = pA[ 5 ] * pB[ 84 ] + pA[ 11 ] * pB[ 85 ] + pA[ 17 ] * pB[ 86 ] + pA[ 23 ] * pB[ 87 ] + pA[ 29 ] * pB[ 88 ] + pA[ 35 ] * pB[ 89 ];
	}
	{
		pX[ 90 ] = pA[ 0 ] * pB[ 90 ] + pA[ 6 ] * pB[ 91 ] + pA[ 12 ] * pB[ 92 ] + pA[ 18 ] * pB[ 93 ] + pA[ 24 ] * pB[ 94 ] + pA[ 30 ] * pB[ 95 ];
		pX[ 91 ] = pA[ 1 ] * pB[ 90 ] + pA[ 7 ] * pB[ 91 ] + pA[ 13 ] * pB[ 92 ] + pA[ 19 ] * pB[ 93 ] + pA[ 25 ] * pB[ 94 ] + pA[ 31 ] * pB[ 95 ];
		pX[ 92 ] = pA[ 2 ] * pB[ 90 ] + pA[ 8 ] * pB[ 91 ] + pA[ 14 ] * pB[ 92 ] + pA[ 20 ] * pB[ 93 ] + pA[ 26 ] * pB[ 94 ] + pA[ 32 ] * pB[ 95 ];
		pX[ 93 ] = pA[ 3 ] * pB[ 90 ] + pA[ 9 ] * pB[ 91 ] + pA[ 15 ] * pB[ 92 ] + pA[ 21 ] * pB[ 93 ] + pA[ 27 ] * pB[ 94 ] + pA[ 33 ] * pB[ 95 ];
		pX[ 94 ] = pA[ 4 ] * pB[ 90 ] + pA[ 10 ] * pB[ 91 ] + pA[ 16 ] * pB[ 92 ] + pA[ 22 ] * pB[ 93 ] + pA[ 28 ] * pB[ 94 ] + pA[ 34 ] * pB[ 95 ];
		pX[ 95 ] = pA[ 5 ] * pB[ 90 ] + pA[ 11 ] * pB[ 91 ] + pA[ 17 ] * pB[ 92 ] + pA[ 23 ] * pB[ 93 ] + pA[ 29 ] * pB[ 94 ] + pA[ 35 ] * pB[ 95 ];
	}
	{
		pX[ 96 ] = pA[ 0 ] * pB[ 96 ] + pA[ 6 ] * pB[ 97 ] + pA[ 12 ] * pB[ 98 ] + pA[ 18 ] * pB[ 99 ] + pA[ 24 ] * pB[ 100 ] + pA[ 30 ] * pB[ 101 ];
		pX[ 97 ] = pA[ 1 ] * pB[ 96 ] + pA[ 7 ] * pB[ 97 ] + pA[ 13 ] * pB[ 98 ] + pA[ 19 ] * pB[ 99 ] + pA[ 25 ] * pB[ 100 ] + pA[ 31 ] * pB[ 101 ];
		pX[ 98 ] = pA[ 2 ] * pB[ 96 ] + pA[ 8 ] * pB[ 97 ] + pA[ 14 ] * pB[ 98 ] + pA[ 20 ] * pB[ 99 ] + pA[ 26 ] * pB[ 100 ] + pA[ 32 ] * pB[ 101 ];
		pX[ 99 ] = pA[ 3 ] * pB[ 96 ] + pA[ 9 ] * pB[ 97 ] + pA[ 15 ] * pB[ 98 ] + pA[ 21 ] * pB[ 99 ] + pA[ 27 ] * pB[ 100 ] + pA[ 33 ] * pB[ 101 ];
		pX[ 100 ] = pA[ 4 ] * pB[ 96 ] + pA[ 10 ] * pB[ 97 ] + pA[ 16 ] * pB[ 98 ] + pA[ 22 ] * pB[ 99 ] + pA[ 28 ] * pB[ 100 ] + pA[ 34 ] * pB[ 101 ];
		pX[ 101 ] = pA[ 5 ] * pB[ 96 ] + pA[ 11 ] * pB[ 97 ] + pA[ 17 ] * pB[ 98 ] + pA[ 23 ] * pB[ 99 ] + pA[ 29 ] * pB[ 100 ] + pA[ 35 ] * pB[ 101 ];
	}
	{
		pX[ 102 ] = pA[ 0 ] * pB[ 102 ] + pA[ 6 ] * pB[ 103 ] + pA[ 12 ] * pB[ 104 ] + pA[ 18 ] * pB[ 105 ] + pA[ 24 ] * pB[ 106 ] + pA[ 30 ] * pB[ 107 ];
		pX[ 103 ] = pA[ 1 ] * pB[ 102 ] + pA[ 7 ] * pB[ 103 ] + pA[ 13 ] * pB[ 104 ] + pA[ 19 ] * pB[ 105 ] + pA[ 25 ] * pB[ 106 ] + pA[ 31 ] * pB[ 107 ];
		pX[ 104 ] = pA[ 2 ] * pB[ 102 ] + pA[ 8 ] * pB[ 103 ] + pA[ 14 ] * pB[ 104 ] + pA[ 20 ] * pB[ 105 ] + pA[ 26 ] * pB[ 106 ] + pA[ 32 ] * pB[ 107 ];
		pX[ 105 ] = pA[ 3 ] * pB[ 102 ] + pA[ 9 ] * pB[ 103 ] + pA[ 15 ] * pB[ 104 ] + pA[ 21 ] * pB[ 105 ] + pA[ 27 ] * pB[ 106 ] + pA[ 33 ] * pB[ 107 ];
		pX[ 106 ] = pA[ 4 ] * pB[ 102 ] + pA[ 10 ] * pB[ 103 ] + pA[ 16 ] * pB[ 104 ] + pA[ 22 ] * pB[ 105 ] + pA[ 28 ] * pB[ 106 ] + pA[ 34 ] * pB[ 107 ];
		pX[ 107 ] = pA[ 5 ] * pB[ 102 ] + pA[ 11 ] * pB[ 103 ] + pA[ 17 ] * pB[ 104 ] + pA[ 23 ] * pB[ 105 ] + pA[ 29 ] * pB[ 106 ] + pA[ 35 ] * pB[ 107 ];
	}
	{
		pX[ 108 ] = pA[ 0 ] * pB[ 108 ] + pA[ 6 ] * pB[ 109 ] + pA[ 12 ] * pB[ 110 ] + pA[ 18 ] * pB[ 111 ] + pA[ 24 ] * pB[ 112 ] + pA[ 30 ] * pB[ 113 ];
		pX[ 109 ] = pA[ 1 ] * pB[ 108 ] + pA[ 7 ] * pB[ 109 ] + pA[ 13 ] * pB[ 110 ] + pA[ 19 ] * pB[ 111 ] + pA[ 25 ] * pB[ 112 ] + pA[ 31 ] * pB[ 113 ];
		pX[ 110 ] = pA[ 2 ] * pB[ 108 ] + pA[ 8 ] * pB[ 109 ] + pA[ 14 ] * pB[ 110 ] + pA[ 20 ] * pB[ 111 ] + pA[ 26 ] * pB[ 112 ] + pA[ 32 ] * pB[ 113 ];
		pX[ 111 ] = pA[ 3 ] * pB[ 108 ] + pA[ 9 ] * pB[ 109 ] + pA[ 15 ] * pB[ 110 ] + pA[ 21 ] * pB[ 111 ] + pA[ 27 ] * pB[ 112 ] + pA[ 33 ] * pB[ 113 ];
		pX[ 112 ] = pA[ 4 ] * pB[ 108 ] + pA[ 10 ] * pB[ 109 ] + pA[ 16 ] * pB[ 110 ] + pA[ 22 ] * pB[ 111 ] + pA[ 28 ] * pB[ 112 ] + pA[ 34 ] * pB[ 113 ];
		pX[ 113 ] = pA[ 5 ] * pB[ 108 ] + pA[ 11 ] * pB[ 109 ] + pA[ 17 ] * pB[ 110 ] + pA[ 23 ] * pB[ 111 ] + pA[ 29 ] * pB[ 112 ] + pA[ 35 ] * pB[ 113 ];
	}
	{
		pX[ 114 ] = pA[ 0 ] * pB[ 114 ] + pA[ 6 ] * pB[ 115 ] + pA[ 12 ] * pB[ 116 ] + pA[ 18 ] * pB[ 117 ] + pA[ 24 ] * pB[ 118 ] + pA[ 30 ] * pB[ 119 ];
		pX[ 115 ] = pA[ 1 ] * pB[ 114 ] + pA[ 7 ] * pB[ 115 ] + pA[ 13 ] * pB[ 116 ] + pA[ 19 ] * pB[ 117 ] + pA[ 25 ] * pB[ 118 ] + pA[ 31 ] * pB[ 119 ];
		pX[ 116 ] = pA[ 2 ] * pB[ 114 ] + pA[ 8 ] * pB[ 115 ] + pA[ 14 ] * pB[ 116 ] + pA[ 20 ] * pB[ 117 ] + pA[ 26 ] * pB[ 118 ] + pA[ 32 ] * pB[ 119 ];
		pX[ 117 ] = pA[ 3 ] * pB[ 114 ] + pA[ 9 ] * pB[ 115 ] + pA[ 15 ] * pB[ 116 ] + pA[ 21 ] * pB[ 117 ] + pA[ 27 ] * pB[ 118 ] + pA[ 33 ] * pB[ 119 ];
		pX[ 118 ] = pA[ 4 ] * pB[ 114 ] + pA[ 10 ] * pB[ 115 ] + pA[ 16 ] * pB[ 116 ] + pA[ 22 ] * pB[ 117 ] + pA[ 28 ] * pB[ 118 ] + pA[ 34 ] * pB[ 119 ];
		pX[ 119 ] = pA[ 5 ] * pB[ 114 ] + pA[ 11 ] * pB[ 115 ] + pA[ 17 ] * pB[ 116 ] + pA[ 23 ] * pB[ 117 ] + pA[ 29 ] * pB[ 118 ] + pA[ 35 ] * pB[ 119 ];
	}
	{
		pX[ 120 ] = pA[ 0 ] * pB[ 120 ] + pA[ 6 ] * pB[ 121 ] + pA[ 12 ] * pB[ 122 ] + pA[ 18 ] * pB[ 123 ] + pA[ 24 ] * pB[ 124 ] + pA[ 30 ] * pB[ 125 ];
		pX[ 121 ] = pA[ 1 ] * pB[ 120 ] + pA[ 7 ] * pB[ 121 ] + pA[ 13 ] * pB[ 122 ] + pA[ 19 ] * pB[ 123 ] + pA[ 25 ] * pB[ 124 ] + pA[ 31 ] * pB[ 125 ];
		pX[ 122 ] = pA[ 2 ] * pB[ 120 ] + pA[ 8 ] * pB[ 121 ] + pA[ 14 ] * pB[ 122 ] + pA[ 20 ] * pB[ 123 ] + pA[ 26 ] * pB[ 124 ] + pA[ 32 ] * pB[ 125 ];
		pX[ 123 ] = pA[ 3 ] * pB[ 120 ] + pA[ 9 ] * pB[ 121 ] + pA[ 15 ] * pB[ 122 ] + pA[ 21 ] * pB[ 123 ] + pA[ 27 ] * pB[ 124 ] + pA[ 33 ] * pB[ 125 ];
		pX[ 124 ] = pA[ 4 ] * pB[ 120 ] + pA[ 10 ] * pB[ 121 ] + pA[ 16 ] * pB[ 122 ] + pA[ 22 ] * pB[ 123 ] + pA[ 28 ] * pB[ 124 ] + pA[ 34 ] * pB[ 125 ];
		pX[ 125 ] = pA[ 5 ] * pB[ 120 ] + pA[ 11 ] * pB[ 121 ] + pA[ 17 ] * pB[ 122 ] + pA[ 23 ] * pB[ 123 ] + pA[ 29 ] * pB[ 124 ] + pA[ 35 ] * pB[ 125 ];
	}
	{
		pX[ 126 ] = pA[ 0 ] * pB[ 126 ] + pA[ 6 ] * pB[ 127 ] + pA[ 12 ] * pB[ 128 ] + pA[ 18 ] * pB[ 129 ] + pA[ 24 ] * pB[ 130 ] + pA[ 30 ] * pB[ 131 ];
		pX[ 127 ] = pA[ 1 ] * pB[ 126 ] + pA[ 7 ] * pB[ 127 ] + pA[ 13 ] * pB[ 128 ] + pA[ 19 ] * pB[ 129 ] + pA[ 25 ] * pB[ 130 ] + pA[ 31 ] * pB[ 131 ];
		pX[ 128 ] = pA[ 2 ] * pB[ 126 ] + pA[ 8 ] * pB[ 127 ] + pA[ 14 ] * pB[ 128 ] + pA[ 20 ] * pB[ 129 ] + pA[ 26 ] * pB[ 130 ] + pA[ 32 ] * pB[ 131 ];
		pX[ 129 ] = pA[ 3 ] * pB[ 126 ] + pA[ 9 ] * pB[ 127 ] + pA[ 15 ] * pB[ 128 ] + pA[ 21 ] * pB[ 129 ] + pA[ 27 ] * pB[ 130 ] + pA[ 33 ] * pB[ 131 ];
		pX[ 130 ] = pA[ 4 ] * pB[ 126 ] + pA[ 10 ] * pB[ 127 ] + pA[ 16 ] * pB[ 128 ] + pA[ 22 ] * pB[ 129 ] + pA[ 28 ] * pB[ 130 ] + pA[ 34 ] * pB[ 131 ];
		pX[ 131 ] = pA[ 5 ] * pB[ 126 ] + pA[ 11 ] * pB[ 127 ] + pA[ 17 ] * pB[ 128 ] + pA[ 23 ] * pB[ 129 ] + pA[ 29 ] * pB[ 130 ] + pA[ 35 ] * pB[ 131 ];
	}
	{
		pX[ 132 ] = pA[ 0 ] * pB[ 132 ] + pA[ 6 ] * pB[ 133 ] + pA[ 12 ] * pB[ 134 ] + pA[ 18 ] * pB[ 135 ] + pA[ 24 ] * pB[ 136 ] + pA[ 30 ] * pB[ 137 ];
		pX[ 133 ] = pA[ 1 ] * pB[ 132 ] + pA[ 7 ] * pB[ 133 ] + pA[ 13 ] * pB[ 134 ] + pA[ 19 ] * pB[ 135 ] + pA[ 25 ] * pB[ 136 ] + pA[ 31 ] * pB[ 137 ];
		pX[ 134 ] = pA[ 2 ] * pB[ 132 ] + pA[ 8 ] * pB[ 133 ] + pA[ 14 ] * pB[ 134 ] + pA[ 20 ] * pB[ 135 ] + pA[ 26 ] * pB[ 136 ] + pA[ 32 ] * pB[ 137 ];
		pX[ 135 ] = pA[ 3 ] * pB[ 132 ] + pA[ 9 ] * pB[ 133 ] + pA[ 15 ] * pB[ 134 ] + pA[ 21 ] * pB[ 135 ] + pA[ 27 ] * pB[ 136 ] + pA[ 33 ] * pB[ 137 ];
		pX[ 136 ] = pA[ 4 ] * pB[ 132 ] + pA[ 10 ] * pB[ 133 ] + pA[ 16 ] * pB[ 134 ] + pA[ 22 ] * pB[ 135 ] + pA[ 28 ] * pB[ 136 ] + pA[ 34 ] * pB[ 137 ];
		pX[ 137 ] = pA[ 5 ] * pB[ 132 ] + pA[ 11 ] * pB[ 133 ] + pA[ 17 ] * pB[ 134 ] + pA[ 23 ] * pB[ 135 ] + pA[ 29 ] * pB[ 136 ] + pA[ 35 ] * pB[ 137 ];
	}
	{
		pX[ 138 ] = pA[ 0 ] * pB[ 138 ] + pA[ 6 ] * pB[ 139 ] + pA[ 12 ] * pB[ 140 ] + pA[ 18 ] * pB[ 141 ] + pA[ 24 ] * pB[ 142 ] + pA[ 30 ] * pB[ 143 ];
		pX[ 139 ] = pA[ 1 ] * pB[ 138 ] + pA[ 7 ] * pB[ 139 ] + pA[ 13 ] * pB[ 140 ] + pA[ 19 ] * pB[ 141 ] + pA[ 25 ] * pB[ 142 ] + pA[ 31 ] * pB[ 143 ];
		pX[ 140 ] = pA[ 2 ] * pB[ 138 ] + pA[ 8 ] * pB[ 139 ] + pA[ 14 ] * pB[ 140 ] + pA[ 20 ] * pB[ 141 ] + pA[ 26 ] * pB[ 142 ] + pA[ 32 ] * pB[ 143 ];
		pX[ 141 ] = pA[ 3 ] * pB[ 138 ] + pA[ 9 ] * pB[ 139 ] + pA[ 15 ] * pB[ 140 ] + pA[ 21 ] * pB[ 141 ] + pA[ 27 ] * pB[ 142 ] + pA[ 33 ] * pB[ 143 ];
		pX[ 142 ] = pA[ 4 ] * pB[ 138 ] + pA[ 10 ] * pB[ 139 ] + pA[ 16 ] * pB[ 140 ] + pA[ 22 ] * pB[ 141 ] + pA[ 28 ] * pB[ 142 ] + pA[ 34 ] * pB[ 143 ];
		pX[ 143 ] = pA[ 5 ] * pB[ 138 ] + pA[ 11 ] * pB[ 139 ] + pA[ 17 ] * pB[ 140 ] + pA[ 23 ] * pB[ 141 ] + pA[ 29 ] * pB[ 142 ] + pA[ 35 ] * pB[ 143 ];
	}
	return true;
}

これを100万回ループします。OpenMPで並列化したソースを、(a)(b)それぞれ以下に示します。ループの並列化は、parallel forではなく、並列スレッドを作成してから配列をmax_thread数で分割し、それぞれのスレッドでループしております。こちらの方がメモリに連続配置されたデータへのアクセスがし易いであろう、との目論見からです。

(a)の100万回ループ実装

// ==============================================================================
//	(a)
// ==============================================================================
bool	loop_mmult_a( double* prA , const size_t nElm , const size_t nElmAll ){
#pragma omp parallel
	{
		//	スレッド数とこのスレッドindexを取得
		const int nThreadMax = omp_get_max_threads();
		const int iThread    = omp_get_thread_num();

		//	1スレッド当たりで計算する要素数
		const int64_t	nElm_local = nElm / nThreadMax;

		//	このスレッドで計算する[A]行列の配列の先頭ポインタ
		double* prA_local = prA + ( nElm_local * iThread * nElmAll );

		//	各スレッドで分担して100万回計算します
		for( int64_t i = 0; i < nElm_local / 10; i++ ){
			//	10回アンローリング
			mmultABX_a( prA_local );	prA_local += nElmAll;
			mmultABX_a( prA_local );	prA_local += nElmAll;
			mmultABX_a( prA_local );	prA_local += nElmAll;
			mmultABX_a( prA_local );	prA_local += nElmAll;
			mmultABX_a( prA_local );	prA_local += nElmAll;
			mmultABX_a( prA_local );	prA_local += nElmAll;
			mmultABX_a( prA_local );	prA_local += nElmAll;
			mmultABX_a( prA_local );	prA_local += nElmAll;
			mmultABX_a( prA_local );	prA_local += nElmAll;
			mmultABX_a( prA_local );	prA_local += nElmAll;
		}
	}

	return	true;
}

(b)の100万回ループ実装


// ==============================================================================
//	(b)
// ==============================================================================
bool	loop_mmult_b(
	double*			prA,	double*			prB,	double*			prX,
	const size_t	nAelm,	const size_t	nBelm,	const size_t	nXelm, 
	const size_t	nElm,
	const size_t	nElmAll ){
#pragma omp parallel
	{
		//	スレッド数とこのスレッドindexを取得
		const int nThreadMax = omp_get_max_threads();
		const int iThread    = omp_get_thread_num();

		//	1スレッド当たりで計算する要素数
		const int64_t	nElm_local = nElm / nThreadMax;

		//	このスレッドで計算する[A][B][X]行列の配列のそれぞれの先頭ポインタ
		double* prA_local = prA + ( nElm_local * iThread * nAelm );
		double* prB_local = prB + ( nElm_local * iThread * nBelm );
		double* prX_local = prX + ( nElm_local * iThread * nXelm );

		//	各スレッドで分担して100万回計算します
		for( int64_t i = 0; i < nElm_local / 10; i++ ){
			//	10回アンローリング
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
			mmultABX_b( prA_local, prB_local, prX_local );	prA_local += nAelm;	prB_local += nBelm;	prX_local += nXelm;
		}
	}

	return	true;
}

#計算結果
(a)(b)を比較した結果を示します。下記はOpenMPにより並列化した場合の結果です。(シリアル処理でも行ったのですが、(a)(b)に差は出ませんでした。)

(a) (b)
計算時間 (s) 計算速度(GFLOPS) 計算時間 (s) 計算速度(GFLOPS)
1回目 0.225 7.10 0.156 10.2
2回目 0.229 6.91 0.153 10.4
3回目 0.221 7.16 0.152 10.4
平均 0.224 7.06 0.153 10.3
※計算速度(GFLOPS)は、2つ行列[A][B]の積における浮動小数点演算回数(1584x100万回)を計算時間で割って求めました。

(a)と(b)の比較は、期待に反して、(b)の方が(a)よりも約45%も高速という結果となりました。10GFLOPSというのは速すぎる気もしますが…(~_~;)。(CPUベンチマーク[2]をご参照)

当方の環境は下記です。

CPU Core i5 3550 ( ivy bridge )
Memory 32 GB(DDR3 1333 MHz)
Compiler Visual C++ 2017

#結論
 ともあれ、長く疑問に思っていた有限要素法における小行列の格納形式について、2つの手法を計測により比較した結果、A,B,Xを各個に連続してメモリに配置する(b)の方法が計算速度に有利、という結果が得られました。これを持って最終判断をするには至りませんが、参考値として活かせれば良いかと考えております。

参考文献
[1] Fortran90/95による有限要素法プログラミング, 藤井文夫,田中真人,佐藤維美著,丸善出版
[2] https://asteroidsathome.net/boinc/cpu_list.php

6
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?