Я пытаюсь пройти через два вектора, вычислить разницу между координатами, вычислить еще немного силы, используя массу и т. д., и актуализировать значение ускорения в каждом цикле, который выполняет тяга:: for_each. Однако я не могу отслеживать значение ускорения.
Используя Thrust и функторы, мне удалось написать это:
Это функтор, который вызывает у меня проблемы:
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-й частицы
вот два разных результата:
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-588854768_32764
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-588854768_32764
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-588854768_32764
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-588854768_32764
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-588854768_32764
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-588854768_32764
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-588854768_32764
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-588854768_32764
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-588854768_32764
0thrust::device_vector<int> vecPosX(10, 10;
thrust::device_vector<int> vecPosY(10, 10);
thrust::device_vector<int> vecPosZ(10, 10);
-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:
Прошу прощения за плохое объяснение, пожалуйста, потерпите меня. Вот полный, простой, компилируемый и работоспособный пример ожидаемых и неожиданных результатов:
пример.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, используя тягу (поскольку он проходит через кучу элементов в векторе) и обновить векторы с результатом тяги for_each.
Как я могу безопасно посчитать ax, ay и az и вернуть их?
частицы, которые вы видите,
std::vector<Particle *> particles;
а Particle — это класс, в котором есть переменные-члены.
int mPosX, mPoY, mPosZ;
float xVel, yVel, zVel;
int mass;
и дт:
const float dt = 0.1f;
Поэтому вместо класса, содержащего целые числа и числа с плавающей запятой, я создал векторы целых чисел и чисел с плавающей запятой, чтобы i-й элемент каждого вектора (вектор массы, скорости, положения) соответствовал информации об одной конкретной частице.