2011-11-10 8 views
3

一部のコードでは、SSEに変換しました。__m128データ型を使用して、一度に4つの光線をトレースしてレイトレーシングを行います。配列をインデックスするために__m128から整数を抽出するSSE

どのオブジェクトが最初にヒットするかを決定する方法では、すべてのオブジェクトをループして交差をテストし、以前に見つかった交差点よりも早い交差点を持つマスクを作成します。

また、ベストヒットタイムに対応するオブジェクトのIDに関するデータも保持する必要があります。私はobjectNo呼ば__m128データ型を維持することによって、これを行うと、以下のようにIはobjectNo更新する交差時間から求めたマスクを使用する:pobj->のgetIdは()のIDを表す整数を返します

objectNo = _mm_blendv_ps(objectNo,_mm_set1_ps((float)pobj->getID()),mask); 

現在のオブジェクト。このキャストを作成し、ブレンドを使用することは、オブジェクトを4つのすべての光線に対して更新する最も効率的な方法であるように見えました。

すべての交差点がテストされた後、私はobjectNoを個別に抽出し、それらを使って交差点を登録する配列にアクセスします。最も一般的に私はこれを試してみました:

int o0 = _mm_extract_ps(objectNo, 0); 
prv_noHits[o0]++; 

しかし、これは1065353216.

がどのように私が正しくすることができint型に__m128を解凍しない値のint型に値を1.0変換をfloatを抽出するようEXC_BAD_ACCESSでクラッシュ配列のインデックスに使用されますか?

答えて

4

あなたがやりたいように見える2つのSSE2変換の組み込み関数があります。

  • _mm_cvtps_epi32()
  • _mm_cvttps_epi32()

http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/intref_cls/common/intref_sse2_int_conversion.htm

これらは4に4単精度FPを変換します32ビット整数。最初の人は丸めでそれを行います。 2番目は切り捨てを使用します。

だから、彼らがこのように使用することができます:

int o0 = _mm_extract_epi32(_mm_cvtps_epi32(objectNo), 0); 
prv_noHits[o0]++; 

EDIT:あなたが何をしようとしてに基づいて、私は次のように、これは、より良い最適化することができ感じる:

__m128i ids = _mm_set1_epi32(pobj->getID()); 

// The mask will need to change 
objectNo = _mm_blend_epi16(objectNo,ids,mask); 

int o0 = _mm_extract_epi32(objectNo, 0); 
prv_noHits[o0]++; 

このバージョンは、不要な変換を取り除きます。しかし、別のマスクベクトルを使用する必要があります。

EDIT 2:固有_mm_castsi128_ps()は任意の命令をマッピングしていないこと

__m128 ids = _mm_castsi128_ps(_mm_set1_epi32(pobj->getID())); 

objectNo = _mm_blendv_ps(objectNo,ids,mask); 

int o0 = _mm_extract_ps(objectNo, 0); 
prv_noHits[o0]++; 

注:あなたがあなたのマスクを変更する必要がないように、ここでの方法です。これは、C/C++の "typeness"を回避するために、ビット単位のデータ型変換__m128iから__m128までです。

+0

ありがとうございました。はい、2番目の方法は最適ですが、本当に最適な方法は、__m128マスクを__m128iマスクに直接変換できるかどうかです。 – cubiclewar

+0

EDIT 2ソリューションを使用すると、最初のソリューションを使用して見た2.3に対して、3.9のスピードアップを達成することができました。キャストのコストの教訓(_mm_cvtps_epi32)。 – cubiclewar

関連する問題