Управление индексными переменными в C ++ AMP - PullRequest
0 голосов
/ 13 января 2012

Я только начал пробовать 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;
}

Однако, как вы можете видеть, это не учитывает свойство симметриидистанционных матриц.Когда я вычисляю sqrsum матриц i и j , я не хочу делать то же самое вычисление снова, когда порядок i и j поменялись местами.Есть ли способ сделать это?Я придумал следующий трюк, но я не знаю, значительно ли это повысит производительность

    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 выполнить работу?Или вы думаете, что заявление if повредит производительности без необходимости?Я не мог придумать никакой альтернативы этому


Кстати, я только что заметил, что написанный выше код не работает на моей машине, чей GPU поддерживает только одинарную точность.Есть что-нибудь сделать, чтобы обойти эту проблему?Сообщение об ошибке выглядит следующим образом: «runtime_exception: Concurrency ;; parallel_for_each использует функции, не поддерживаемые выбранным ускорителем. ID3D11Device :: CreateComputeShader: Shader использует операции с плавающей запятой двойной точности, которые не поддерживаются на текущем устройстве.»

1 Ответ

2 голосов
/ 14 января 2012

Я думаю, что вы можете устранить условие if, если бы вы планировали столько потоков, сколько вам нужно, вместо планирования всего прямоугольника, который покрывает вашу выходную матрицу.Вам нужен верхний или нижний треугольник без диагонали, который вы можете вычислить, используя арифметическую последовательность.

Альтернативой может быть организация входных данных таким образом, чтобы они находились в двух одномерных векторах, каждый поток считывал значение из вектора 1, затем из вектора 2, вычислял расстояние и сохранял его в одном из входных векторов.

Наконец, появляется ошибка двойной точности, поскольку используемая карта не поддерживает операции двойной точности.Пожалуйста, проверьте спецификацию вашей карты, чтобы подтвердить это.Вы можете обойти это, переключившись на тип с одинарной точностью, т.е. "float" в шаблоне array_view.

...