0

当我将 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";
}
4

0 回答 0