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 条件可以完成这项工作吗?还是您认为 if 语句会不必要地损害性能?我想不出任何替代方案


顺便说一句,我刚刚注意到上面写的代码在我的机器上不起作用,它的 gpu 只支持单精度。有什么办法可以解决这个问题吗?错误消息如下:“runtime_exception: Concurrency;;parallel_for_each 使用所选加速器不支持的功能。ID3D11Device::CreateComputeShader: Shader 使用当前设备不支持的双精度浮点操作。”

4

1 回答 1

2

我认为您可以消除 if 条件,如果您只安排所需数量的线程,而不是安排覆盖输出矩阵的整个矩形。您需要的是没有对角线的上三角形或下三角形,您可以使用等差数列计算。

另一种方法是组织输入数据,使其位于两个 1D 向量中,每个线程将从向量 1 中读取值,然后从向量 2 中读取值并计算距离并将其存储在输入向量之一中。

最后,出现双精度错误,因为您使用的卡不支持双精度操作。请检查您的卡规格以确认。您可以通过切换到单精度类型,即 array_view 模板中的“float”来解决它。

于 2012-01-14T04:49:43.763 回答