具有推力内部状态的仿函数

时间:2015-08-16 09:25:39

标签: c++ cuda functor thrust

我试图通过两个向量,计算坐标之间的差异,使用质量计算一些更大的力等,并在thrust :: for_each的每个循环上实现加速度值。但是,我无法跟踪加速度值。

使用Thrust和functor,我设法写了这个:

这是给我带来麻烦的仿函数:

struct ParticleGenerator::acc_func{
    //stores the initial coordinates if i-th particle to use it for computation and the init. acc. that is 0.0f
    acc_func(float Ax, float Bx, float Cx, int X, int Y, int Z) : ax(Ax), bx(Bx), cx(Cx),  _x(X), _y(Y), _z(Z) {}

    template <typename Tuple>
    __device__ __host__
    void operator()(Tuple t){
            //thrust::get<0>(t) +=(int) 32;
            // save some values
            acc[0] = thrust::get<0>(t);  //(#)
            acc[1] = thrust::get<1>(t);
            acc2[0] = acc[0];
            acc2[1] = acc[1];
            //retrieve them, OK
            printf("%d_%d\n", acc[0], acc[1]); //works well
    }


    int getRes(){
            //return saved values, not OK
            printf("%d_%d_%d_%d\n", acc[0], acc[1], acc2[0], acc2[1]); //prints wrong values

            return 0;
    }

    //this returns the correct value, though
    int getRes2(){ return _x;}

    int acc2[2];
private:
        float ax, bx, cx;
        int _x, _y, _z;
        int temp;
        int acc[2];
};

正如您所看到的,我已经尝试过公共和私有,也尝试使用简单的int( temp )来存储任何值,但函数 getRes()如下所示,永远不会返回正确的值。

我注意到部件 _x(X)(向右滚动以查看acc_func()的完整构造函数)正确存储值,我可以使用函数检索它 getRes()

问题:有没有办法如何复制这种行为?要在标有//(#)的行上使用该命令并成功保存,更新并稍后返回值?

这是我的推力循环:

for(unsigned int i = 0; i < vecPosX.size(); ++i){   
    acc_func AF(0.0f, 0.0f, 0.0f, vecPosX[i], vecPosY[i], vecPosZ[i]);
    thrust::for_each(
                      thrust::make_zip_iterator(thrust::make_tuple(vecPosX.begin(), vecPosY.begin())),
                      thrust::make_zip_iterator(thrust::make_tuple(vecPosX.end(), vecPosY.end())),
                    AF
                    );
    AF.getRes();
    //use the AF.getRes() to save the values of the acceleration and
    //update the vecPosX[i], vecPosY[i] etc accordingly
}

其中vecPosX,vecPosY是影响粒子X和Y位置的载体

整个想法是创建一个元组(posX,posY)并在每个 thrust :: for_each 循环上重新计算并实现加速,当计算完成时,只需返回加速x的结果和y,以便我可以更新第i个粒子的速度和位置

这里有两个不同的结果:

0_4_-588854768_32764
0_4_-588854768_32764
0_4_-588854768_32764
0_4_-588854768_32764
0_4_-588854768_32764
0_4_-588854768_32764
0_4_-588854768_32764
0_4_-588854768_32764
0_4_-588854768_32764
0_4_-588854768_32764
267_264_267_264
254_272_254_272
256_237_256_237
264_264_264_264
259_228_259_228
259_247_259_247
264_245_264_245
265_237_265_237
272_260_272_260

我希望你能帮助我,谢谢你:)。

编辑:请注意我已经使用SDL,Visual Studio和两个for循环一起成功编写了整个模拟应用程序,现在我正在尝试制作能够使用更多粒子的速度更快

编辑2:来复制问题,可以使用

thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);

创建向量和一些值

编辑3:

我为我的错误解释道歉,请耐心等待。 以下是预期和意外结果的完整,简单,可编辑和可运行的示例:

example.cu:

#include <thrust/device_vector.h>
#include <thrust/for_each.h>
#include <thrust/iterator/zip_iterator.h>
#include <iostream>

thrust::device_vector<int> vecPosX(5, 10);
thrust::device_vector<int> vecPosY(5, 10);

struct acc_func {
    acc_func(int X, int Y) : _x(X), _y(Y) {}

    template <typename Tuple>
    __device__ __host__
    void operator()(Tuple t){
            acc2[0] = _x;
            acc2[1] = _y;
            acc[0] += 1;
            acc[1] += 1;
    }


    void expected(){
        printf("expected:\t%d:%d:and:%d:%d\n", 5, 5, _x, _y);
        return;
    }

    void not_expected(){
        printf("unexpected:\t%d:%d:nor:%d:%d\n\n", acc[0], acc[1], acc2[0], acc2[1]);
        return;
    }

public:
        int acc2[2];
private:
        int _x, _y;
        int acc[2] = {0, 0};
};


int main(){

    for(unsigned int i = 0; i < vecPosX.size(); ++i){
        acc_func AF(vecPosX[i], vecPosY[i]);
        thrust::for_each(
            thrust::make_zip_iterator(thrust::make_tuple(vecPosX.begin(),vecPosY.begin())),                      

            thrust::make_zip_iterator(thrust::make_tuple(vecPosX.end(), vecPosY.end())),
            AF
          );
        AF.expected();
        AF.not_expected();
    }

    return 0;


}

结果:

$ nvcc -std=c++11 example.cu -o example
$ ./example
expected:       5:5:and:10:10
unexpected:     0:0:nor:19:0

expected:       5:5:and:10:10
unexpected:     0:0:nor:19:0

expected:       5:5:and:10:10
unexpected:     0:0:nor:19:0

expected:       5:5:and:10:10
unexpected:     0:0:nor:19:0

expected:       5:5:and:10:10
unexpected:     0:0:nor:19:0

编辑4

我想要实现的是重写以下代码:

float ax, ay, az, dx, dy, dz;
float invr, invr3, f;
for(unsigned int i = 0; i < particles.size(); i++){
    ax = 0.0;
    ay = 0.0;
    az = 0.0;


    for(unsigned int j = 0; j < particles.size(); j++){
        dx = (float) (particles[j]->mPosX - particles[i]->mPosX);
        dy = (float) (particles[j]->mPosY - particles[i]->mPosY);
        dz = (float) (particles[j]->mPosZ - particles[i]->mPosZ);
        invr = (float) 1.0/sqrt(dx*dx + dy*dy + dz*dz + 100);
        invr3 = invr*invr*invr;
        f = particles[j]->mass * invr3;
        ax += f*dx;
        ay += f*dy;
        az += f*dz;
    }
    particles[i]->mPosX = particles[i]->mPosX + (int) dt*particles[i]->xVel + (int) 0.5*dt*dt*ax;
    particles[i]->mPosY = particles[i]->mPosY + (int) dt*particles[i]->yVel + (int) 0.5*dt*dt*ay;
    particles[i]->mPosZ = particles[i]->mPosZ + (int) dt*particles[i]->zVel + (int) 0.5*dt*dt*az;
    particles[i]->xVel += dt*ax;
    particles[i]->yVel += dt*ay;
    particles[i]->zVel += dt*az;
}

我的目的是保持外环非常实际,使用推力计算 ax ay az (因为它& #39; s遍历向量中的一堆元素)并使用结果 for_each 更新向量。

如何安全地计算 ax ay az 并将其返回?

你看到的粒子

std::vector<Particle *> particles;

Particle 是一个具有成员变量的类

int mPosX, mPoY, mPosZ;
float xVel, yVel, zVel;
int mass;

和dt是:

const float dt = 0.1f;

因此,不是包含整数和浮点数的类,而是创建了整数和浮点数的向量,以便每个向量的第i个元素(质量,速度,位置的向量)对应于关于一个特定粒子的信息

0 个答案:

没有答案