Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: [email protected].
*
* Created on 09.02.2004
*/
package net.finmath.montecarlo.cuda.alternative;
import static jcuda.jcurand.JCurand.curandCreateGenerator;
import static jcuda.jcurand.JCurand.curandDestroyGenerator;
import static jcuda.jcurand.JCurand.curandSetPseudoRandomGeneratorSeed;
import static jcuda.jcurand.curandRngType.CURAND_RNG_PSEUDO_DEFAULT;
import static jcuda.runtime.JCuda.cudaFree;
import static jcuda.runtime.JCuda.cudaMalloc;
import static jcuda.runtime.JCuda.cudaMemcpy;
import static jcuda.runtime.cudaMemcpyKind.cudaMemcpyDeviceToHost;
import java.io.Serializable;
import jcuda.Pointer;
import jcuda.Sizeof;
import jcuda.jcurand.JCurand;
import jcuda.jcurand.curandGenerator;
import jcuda.runtime.JCuda;
import net.finmath.montecarlo.AbstractRandomVariableFactory;
import net.finmath.montecarlo.BrownianMotion;
import net.finmath.montecarlo.RandomVariableFactory;
import net.finmath.montecarlo.RandomVariableFromFloatArray;
import net.finmath.stochastic.RandomVariable;
import net.finmath.time.TimeDiscretization;
/**
* Implementation of a time-discrete n-dimensional Brownian motion
* W = (W1,...,Wn) where Wi is
* a Brownian motion and Wi, Wj are
* independent for i not equal j.
*
* For a correlated Brownian motion with see
* {@link net.finmath.montecarlo.CorrelatedBrownianMotion}.
*
* Here the dimension n is called factors since this Brownian motion is used to
* generate multi-dimensional multi-factor Ito processes and there one might
* use a different number of factors to generate Ito processes of different
* dimension.
*
* The quadruppel (time discretization, number of factors, number of paths, seed)
* defines the state of an object of this class, i.e., BrownianMotionLazyInit for which
* there parameters agree, generate the same random numbers.
*
* The class is immutable and thread safe. It uses lazy initialization.
*
* @author Christian Fries
* @version 1.6
*/
public class BrownianMotionCudaWithHostRandomVariable implements BrownianMotion, Serializable {
private static final long serialVersionUID = -5430067621669213475L;
private final TimeDiscretization timeDiscretization;
private final int numberOfFactors;
private final int numberOfPaths;
private final int seed;
private final AbstractRandomVariableFactory randomVariableFactory;
private transient RandomVariable[][] brownianIncrements;
private final Object brownianIncrementsLazyInitLock = new Object();
/**
* Construct a Brownian motion.
*
* The constructor allows to set the factory to be used for the construction of
* random variables. This allows to generate Brownian increments represented
* by different implementations of the RandomVariable (e.g. the RandomVariableFromFloatArray internally
* using float representations).
*
* @param timeDiscretization The time discretization used for the Brownian increments.
* @param numberOfFactors Number of factors.
* @param numberOfPaths Number of paths to simulate.
* @param seed The seed of the random number generator.
* @param randomVariableFactory Factory to be used to create random variable.
*/
public BrownianMotionCudaWithHostRandomVariable(
final TimeDiscretization timeDiscretization,
final int numberOfFactors,
final int numberOfPaths,
final int seed,
final AbstractRandomVariableFactory randomVariableFactory) {
super();
this.timeDiscretization = timeDiscretization;
this.numberOfFactors = numberOfFactors;
this.numberOfPaths = numberOfPaths;
this.seed = seed;
this.randomVariableFactory = new RandomVariableFactory(false); /* randomVariableFactory */
this.brownianIncrements = null; // Lazy initialization
}
/**
* Construct a Brownian motion.
*
* @param timeDiscretization The time discretization used for the Brownian increments.
* @param numberOfFactors Number of factors.
* @param numberOfPaths Number of paths to simulate.
* @param seed The seed of the random number generator.
*/
public BrownianMotionCudaWithHostRandomVariable(
final TimeDiscretization timeDiscretization,
final int numberOfFactors,
final int numberOfPaths,
final int seed) {
this(timeDiscretization, numberOfFactors, numberOfPaths, seed, new RandomVariableFactory());
}
@Override
public BrownianMotion getCloneWithModifiedSeed(final int seed) {
return new BrownianMotionCudaWithHostRandomVariable(getTimeDiscretization(), getNumberOfFactors(), getNumberOfPaths(), seed);
}
@Override
public BrownianMotion getCloneWithModifiedTimeDiscretization(final TimeDiscretization newTimeDiscretization) {
/// @TODO This can be improved: a complete recreation of the Brownian motion wouldn't be necessary!
return new BrownianMotionCudaWithHostRandomVariable(newTimeDiscretization, getNumberOfFactors(), getNumberOfPaths(), getSeed());
}
@Override
public RandomVariable getBrownianIncrement(final int timeIndex, final int factor) {
// Thread safe lazy initialization
synchronized(brownianIncrementsLazyInitLock) {
if(brownianIncrements == null) {
doGenerateBrownianMotion();
}
}
/*
* We return an immutable object which ensures that the receiver does not alter the data.
*/
return brownianIncrements[timeIndex][factor];
}
/**
* Lazy initialization of brownianIncrement. Synchronized to ensure thread safety of lazy init.
*/
private void doGenerateBrownianMotion() {
if(brownianIncrements != null)
{
return; // Nothing to do
}
// Enable exceptions and omit all subsequent error checks
JCuda.setExceptionsEnabled(true);
JCurand.setExceptionsEnabled(true);
final int n = numberOfFactors * numberOfPaths;
final curandGenerator generator = new curandGenerator();
// Allocate n floats on host
// float hostData[] = new float[n];
// Allocate n floats on device
final Pointer deviceData = new Pointer();
cudaMalloc(deviceData, n * Sizeof.FLOAT);
// Create pseudo-random number generator
curandCreateGenerator(generator, CURAND_RNG_PSEUDO_DEFAULT);
// Set seed
curandSetPseudoRandomGeneratorSeed(generator, 1234);
// Allocate memory
final float[][][] brownianIncrementsArray = new float[timeDiscretization.getNumberOfTimeSteps()][numberOfFactors][numberOfPaths];
// Pre-calculate square roots of deltaT
for(int timeIndex=0; timeIndex