質問
はありまasmの指示できる計算の高速化のmin/maxのベクトルのダブル-の整数のコアi7すものでした。
更新:
とは予想していなかったような豊かな回答、お願い申し上げます。なんと最大/最小限なしです。しかし質問
あるのに有効な方法で取得し、指数の最大のダブルアレイ?
解決
はSSE4は有用かもしれない32ビットの符号付き/符号なし整数のためPMAXSD
又はPMAXUD
を有しています。
SSE2を使用すると、負荷と運用の通常のインターレースで、n個のベクトルの最大を取得するために1 MAXSDでのn / 2-1 MAXPDsに従うので、ダブルスのペアの間と間で比較MAXPD
とMAXSD
を持っています。
上記のMIN同等物があります。
は二重のケースでは、あなたはおそらく、SSEモードで半まともなC ++コンパイラよりもアセンブラに優れてやるつもりはない。
peregrino:$ g++ -O3 src/min_max.cpp -o bin/min_max
peregrino:$ g++ -O3 -msse4 -mfpmath=sse src/min_max.cpp -o bin/min_max_sse
peregrino:$ time bin/min_max
0,40
real 0m0.874s
user 0m0.796s
sys 0m0.004s
peregrino:$ time bin/min_max_sse
0,40
real 0m0.457s
user 0m0.404s
sys 0m0.000s
min_maxは分および500倍のアレイの最大値を計算し、ナイーブループを用いて10万倍
bool min_max ( double array[], size_t len, double& min, double& max )
{
double min_value = array [ 0 ];
double max_value = array [ 0 ];
for ( size_t index = 1; index < len; ++index ) {
if ( array [ index ] < min_value ) min_value = array [ index ];
if ( array [ index ] > max_value ) max_value = array [ index ];
}
min = min_value;
max = max_value;
}
<時間>
は第二部に応答して、最大動作から分岐を除去するための伝統的な最適化値を比較することで、単一ビット(0または1を与える)、(0または0xffff_ffffを与える)減算としてフラグを取得し、「と'は2つの可能な結果のXORと、あなたが( a > best ? ( current_index ^ best_index ) : 0 ) ^ best_index )
相当を取得するようにします。私は、SSEがパック値ではなく、タグ付き値を操作する傾向があるという理由だけで、それを行うの簡単なSSEの方法があります疑います。そこにあなたが元のベクトルのすべての要素から、その後、符号ビットを収集することを差し引いた後、最大の発見を試みることができるように、いくつかの水平方向のインデックス操作は、あり、そしてゼロ署名1は、最大のインデックスに対応するであろうが、それはおそらくだろうあなたはショートパンツやバイトを使用していた場合を除き改善されません。
他のヒント
MAXPSとMINPS両方パックド単精度浮動小数点数で動作します。 PMAXSW、PMINSW、PMAXUBとPMINUBは、すべての符号付きまたは符号なしのいずれかで、パックされた8ビット・ワードで動作します。くださいこれらの要素単位二つの入力SSEレジスタ又はアドレス位置を比較し、SSEレジスタまたはメモリ位置に結果を格納することに注意してください。
MAXPSとMINPSのSSE2バージョンは倍精度浮動小数点数で動作する必要があります。
あなたは何のコンパイラと最適化フラグを使用していますか?それらをターゲットサポートしている場合は、GCC 4.0とよりよいが自動的に操作をベクトル化する必要があり、以前のバージョンでは、特定のフラグが必要な場合があります。
あなたは、Intelの IPP のライブラリを使用している場合は、ベクターを使用することができます統計関数を計算するためのを(とりわけ)、ベクトル最小/最大
お客様の第二の質問:ほとんどのプラットフォームがライブラリに含まれている最適な実装が実装しこの操作は、他のほとんどの簡単なベクトル操作用) 使用してい.
- OS Xであ
vDSP_maxviD( )
やcblas_idamax( )
では、ますます加速する枠組み - インテルのコンパイラなどの電力事業、MKLライブラリ、高い性能の実装を含む
cblas_idamax( )
- 最Linuxシステムにおいて
cblas_idamax( )
のBLASライブラリであるか否かを問わずどの調整によっては、そのアプロヴェナン;ユーザーに人気性能は一般にて実施又は説き伏ル) - ド利用できるアトラス(自動チューニ線形代数ソフトウェア)ゃ性能の実装では、対象プラットフォーム
更新:はないと言ってました"配列"ではなく、ベクトル"の第2部たことにかく場合に便利であるとはいえるでしょう。
re:第二部:の指標の最大/最小要素でSSEベクトル:
い水平ます。のための128bベクトルの2
double
要素が、それだけshufpd
+maxpd
は放送の両方です。その他の場合には、かかります。見 最速い水平floatベクトル和x86 のためのアイデアを交換
addps
とmaxps
またはminps
.(ただし16ビット整数の特殊利用できSSE4phminposuw
.のための最大max.から減算255)な梱包-の比較の元ベクトルのベクトルのベクトル場の要素はmax.
(
pcmpeqq
整数型ビットパターンは通常のcmpeqpd
うものdouble
例)です。int _mm_movemask_pd (__m128d a)
(movmskpd
) の比較結果を整数値としてのビットマップ.- ビットマスク
bsf
では、最初のマッチ:index = _bit_scan_forward(cmpmask)
.cmpmask=0でご利用いただいていたお客様の整数を比較す(少なくとも一つの要素にマッチしてもNaN)である.
このコンパイルのみ6指示を含む movapd
).そう、確認 のGodboltコンパイラexplorer では、SSE.
#include <immintrin.h>
#include <x86intrin.h>
int maxpos(__m128d v) {
__m128d swapped = _mm_shuffle_pd(v,v, 1);
__m128d maxbcast = _mm_max_pd(swapped, v);
__m128d cmp = _mm_cmpeq_pd(maxbcast, v);
int cmpmask = _mm_movemask_pd(cmp);
return _bit_scan_forward(cmpmask);
}
ご注意 _mm_max_pd
ない可換環とNaN入力.NaNの場合は可能で、どんな性能のインテルNehalemする検討 _mm_cmpeq_epi64
比較-ビットパターンバイパス遅延から浮かびvec-int問題にNehalemれています。
NaN!= NaN IEEE浮動小数点での _mm_cmpeq_pd
結果をマスクすべてゼロにNaNます。
もうひとつできるおもてなしの2要素の場合には常に0または1ビットの交換-スキャニング cmpmask >> 1
. (bsf
はっと入力=すべてゼロ).
あなたの2番目の質問に応えて、それはあなたが収集する方法を考えると、このデータを保存するためにあなたに価値があるかもしれません。
あなたはデータを保持してBツリーにデータを格納することができるだけで、対数比較演算を必要とする、すべての回でソートします。
次に、あなたが最大のすべての回で知っています。