当我将 numPaths 增加到 1000000 时,下面的 Monte-Carlo 代码失败(“进程以代码 -2147483645 退出”,价格函数的输出不会被打印),除非我同时减少 numSteps。如果我删除对 curand 的所有引用并使用固定数字,代码总是有效,所以我认为问题与生成太多随机数有关。我尝试使用每个线程的新种子而不是新的子序列来调用 curand_init,但它没有解决问题。
另外,我在使用 Thrust 而不是 curand 生成随机数时遇到了同样的问题。
有人可以帮忙吗?
#include <math.h>
#include <curand_kernel.h>
#include "cuda_runtime.h"
#include <thrust/device_vector.h>
#include <thrust/reduce.h>
#include <thrust/transform_reduce.h>
#include <thrust/transform.h>
#include <thrust/functional.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/zip_iterator.h>
#include <device_launch_parameters.h>
#include <thrust/execution_policy.h>
using State3D = thrust::tuple<double, double, double>;
template<typename State>
struct AbstractModel : public thrust::binary_function<State, int, State>
{
private:
double seed = 0;
int numSteps;
public:
double dt, sqdt;
AbstractModel(double T, int numSteps)
: numSteps(numSteps), dt(T / numSteps), sqdt(sqrt(T / numSteps)) {}
__device__ virtual void nextStep(State& state, curandState &rand_state) const = 0;
__device__ State operator() (const State &state, const int &i) const
{
curandState rand_state;
curand_init(seed, i, 0, &rand_state);
State currentState = state;
for (unsigned i = 0; i < numSteps; i++)
nextStep(currentState, rand_state);
return currentState;
}
};
struct Model : public AbstractModel<State3D>
{
double lambda, m, w, theta, eta;
Model(double T, int numSteps, double lambda, double m, double w, double theta, double eta)
: AbstractModel(T, numSteps), lambda(lambda), m(m), w(w), theta(theta), eta(eta) {}
__device__ void nextStep(State3D &state, curandState &rand_state) const
{
double level = fmax(state.get<2>(), 0.0),
sqlevel = sqrt(level), vol = lambda * sqlevel;
state.get<0>() += vol * sqdt * curand_normal_double(&rand_state);
state.get<1>() += vol * vol * dt;
state.get<2>() += theta * (1.0 - level) * dt + eta * sqlevel * sqdt * curand_normal_double(&rand_state);
}
};
struct ModelInitializer : public thrust::unary_function<int, State3D>
{
__device__ State3D operator() (const int idx) const
{
return thrust::make_tuple<double, double, double>(0.0, 0.0, 0.0);
}
};
struct ModelPayoffTest : public thrust::unary_function<thrust::tuple<double, double, double>, double>
{
double operator()(const thrust::tuple<double, double, double> &state) const
{
return state.get<2>();
}
};
template<typename Model, typename Payoff>
double price(unsigned numPaths, Model &model, Payoff &payoff)
{
thrust::device_vector<State3D> markov_states(numPaths);
//initialize paths with start value
thrust::transform(thrust::make_counting_iterator(0), thrust::make_counting_iterator(0) + numPaths, markov_states.begin(), ModelInitializer()/*model*/);
//diffuse paths
thrust::transform(markov_states.begin(), markov_states.end(), thrust::make_counting_iterator(0)/*rand_states.begin()*/, markov_states.begin(), model);
return thrust::transform_reduce(markov_states.begin(), markov_states.end(), payoff, 0.0, thrust::plus<double>()) / numPaths;
}
int main()
{
double lambda = 0.05, m = 20, w = 0.5, theta = 0.05, eta = 0.1;
double T = 10;
int numSteps = 10 * 365;
Model cheyette(T, numSteps, lambda, m, w, theta, eta);
ModelPayoffTest payoff;
int numPaths = 100000;
std::cout << price<Model, ModelPayoffTest>(numPaths, cheyette, payoff) << "\n";
}