0

私はC++AMPを試し始めたばかりで、現在取り組んでいるプロジェクトで試してみることにしました。ある時点で、私は持っているベクトルの距離行列を作成する必要があり、これのために以下のコードを書きました

unsigned int samplesize=samplelist.size();
unsigned int vs = samplelist.front().size();

vector<double> samplevec(samplesize*vs);
vector<double> distancevec(samplesize*samplesize,0);

it1=samplelist.begin();

for(int i=0 ; i<samplesize; ++i){
    for(int j = 0 ; j<vs ; ++j){
        samplevec[j + i*vs] = (*it1)[j];
    }
    ++it1;
}

array_view<const double,2> samplearray(samplesize,vs,samplevec);
array_view<writeonly<double>,2> distances(samplesize,samplesize,distancevec);

parallel_for_each(distances.grid, [=](index<2> idx) restrict(direct3d){
    double sqrsum=0;
    double tempd=0;

    for ( unsigned int i=0 ; i<vs ; ++i)
    {
        tempd = samplearray(idx.x,i) - samplearray(idx.y,i);
        sqrsum += tempd*tempd;
    }
    distances[idx]=sqrsum;
}

ただし、ご覧のとおり、これは距離行列の対称性を考慮していません。行列ijのsqrsumを計算するとき、 ijの順序が逆になっているときに、同じ計算を再度実行したくありません。これを達成する方法はありますか?私は次のトリックを思いついたが、これがパフォーマンスを大幅に向上させるかどうかはわからない

    for ( unsigned int i=0 ; i<vs ; ++i)
    {
        if(idx.x<=idx.y){
            break;
        }

        tempd = samplearray(idx.x,i) - samplearray(idx.y,i);
        sqrsum += tempd*tempd;
    }

if-conditionはその仕事をすることができますか?それとも、ifステートメントがパフォーマンスを不必要に損なうと思いますか?私はそれに代わるものを思い付くことができませんでした


ところで、上記のコードが私のマシンでは機能しないことに気づきました。そのgpuは単精度しかサポートしていません。その問題を回避するために何かすることはありますか?エラーメッセージは次のとおりです。「runtime_exception:Concurrency ;; parallel_for_eachは、選択したアクセラレータでサポートされていない機能を使用します。ID3D11Device:: CreateComputeShader:Shaderは、現在のデバイスでサポートされていない倍精度浮動小数点演算を使用します。」

4

1 に答える 1

2

出力マトリックスをカバーする長方形全体をスケジュールする代わりに、必要な数のスレッドのみをスケジュールする場合は、if-conditionを排除できると思います。必要なのは、等差数列を使用して計算できる、対角線のない上三角形または下三角形です。

別の方法は、入力データを2つの1Dベクトルに編成し、各スレッドがベクトル1、次にベクトル2から値を読み取り、距離を計算して入力ベクトルの1つに格納するようにすることです。

最後に、使用しているカードが倍精度演算をサポートしていないため、倍精度のエラーが表示されます。カードの仕様を確認してください。単精度型、つまりarray_viewテンプレートの「float」に切り替えることで回避できます。

于 2012-01-14T04:49:43.763 に答える