13
13
14
14
#include < curand_kernel.h>
15
15
16
- void CUDA::Simulation::run_simulation (std::map<XVA, double > xva,
17
- double m0, double m1,
16
+ /* *
17
+ * @brief Generate a sample from a Gaussian distribution
18
+ *
19
+ * @param mean
20
+ * @param std_dev
21
+ * @param state
22
+ * @return double Gaussian sample
23
+ */
24
+ __device__ double generate_gaussian_sample (double mean, double std_dev, curandState *state)
25
+ {
26
+ return mean + std_dev * curand_normal_double (state);
27
+ }
28
+
29
+ /* *
30
+ * @brief Generate the external path for the interest rate on GPU
31
+ *
32
+ * @param paths External paths
33
+ * @param m0 Number of paths
34
+ * @param N Size of each path
35
+ * @param T Time horizon
36
+ */
37
+ __global__ void generate_external_path_interest_rate (double **paths, size_t *m0, size_t *N, double *T)
38
+ {
39
+ double r0 = 0.03 ;
40
+ double k (0.5 );
41
+ double theta = 0.04 ;
42
+ double sigma = 0.1 ;
43
+
44
+ double dt = *T / *N;
45
+
46
+ int idx = blockIdx .x * blockDim .x + threadIdx .x ;
47
+
48
+ curandState state;
49
+ curand_init (1234 , idx, 0 , &state);
50
+
51
+ if (idx < *m0)
52
+ {
53
+ for (size_t i = 0 ; i < *N; i++)
54
+ {
55
+ double dW = generate_gaussian_sample (0 , sqrt (dt), &state);
56
+ paths[idx][i] = paths[idx][i - 1 ] + k * (theta - paths[idx][i - 1 ]) * dt + sigma * dW * sqrt (paths[idx][i - 1 ]);
57
+ }
58
+ }
59
+ }
60
+
61
+ /* *
62
+ * @brief Generate the external path for the FX rate on GPU
63
+ *
64
+ * @param paths External paths
65
+ * @param m0 Number of paths
66
+ * @param N Size of each path
67
+ * @param T Time horizon
68
+ */
69
+ __global__ void generate_external_path_fx (double **paths, size_t *m0, size_t *N, double *T)
70
+ {
71
+ double S0 = 1.15 ;
72
+ double mu = 0.02 ;
73
+ double sigma = 0.1 ;
74
+
75
+ double dt = *T / *N;
76
+
77
+ int idx = blockIdx .x * blockDim .x + threadIdx .x ;
78
+
79
+ curandState state;
80
+ curand_init (1234 , idx, 0 , &state);
81
+
82
+ if (idx < *m0)
83
+ {
84
+ for (size_t i = 0 ; i < *N; i++)
85
+ {
86
+ double dW = generate_gaussian_sample (0 , sqrt (dt), &state);
87
+ paths[idx][i] = paths[idx][i - 1 ] * exp ((mu - 0.5 * sigma * sigma) * dt + sigma * dW);
88
+ }
89
+ }
90
+ }
91
+
92
+ __global__ void generate_external_path_equity (double **paths, size_t *m0, size_t *N, double *T)
93
+ {
94
+ double S0 = 100 ;
95
+ double mu = 0.05 ;
96
+ double sigma = 0.2 ;
97
+
98
+ double dt = *T / *N;
99
+
100
+ int idx = blockIdx .x * blockDim .x + threadIdx .x ;
101
+
102
+ curandState state;
103
+ curand_init (1234 , idx, 0 , &state);
104
+
105
+ if (idx < *m0)
106
+ {
107
+ for (size_t i = 0 ; i < *N; i++)
108
+ {
109
+ double dW = generate_gaussian_sample (0 , sqrt (dt), &state);
110
+ paths[idx][i] = paths[idx][i - 1 ] * exp ((mu - 0.5 * sigma * sigma) * dt + sigma * dW);
111
+ }
112
+ }
113
+ }
114
+
115
+ void CUDA::Simulation::run_simulation (const std::map<XVA, double >& xva,
116
+ size_t m0, size_t m1,
18
117
size_t nb_points, double T,
19
118
std::map<ExternalPaths, std::vector<Vector>> &external_paths,
20
119
std::map<XVA, Vector> &paths)
21
120
{
121
+ double *d_T;
122
+ size_t *d_N, *d_m0, *d_m1;
123
+ double **d_paths;
124
+ double **generated_paths = new double *[m0];
125
+
126
+
127
+ cudaMalloc (&d_m0, sizeof (size_t ));
128
+ cudaMalloc (&d_m1, sizeof (size_t ));
129
+ cudaMalloc (&d_T, sizeof (double ));
130
+ cudaMalloc (&d_N, sizeof (size_t ));
131
+
132
+ cudaMemcpy (d_m0, &m0, sizeof (size_t ), cudaMemcpyHostToDevice);
133
+ cudaMemcpy (d_m1, &m1, sizeof (size_t ), cudaMemcpyHostToDevice);
134
+ cudaMemcpy (d_T, &T, sizeof (double ), cudaMemcpyHostToDevice);
135
+ cudaMemcpy (d_N, &nb_points, sizeof (size_t ), cudaMemcpyHostToDevice);
136
+
137
+ cudaMalloc (&d_paths, m0 * sizeof (double *));
138
+
139
+ for (size_t i = 0 ; i < m0; i++)
140
+ {
141
+ cudaMalloc (&d_paths[i], nb_points * sizeof (double ));
142
+ }
143
+
144
+ generate_external_path_interest_rate<<<m0, 1 >>> (d_paths, d_m0, d_N, d_T);
145
+ for (size_t i = 0 ; i < m0; i++)
146
+ {
147
+ generated_paths[i] = new double [nb_points];
148
+ cudaMemcpy (generated_paths[i], d_paths[i], nb_points * sizeof (double ), cudaMemcpyDeviceToHost);
149
+ external_paths[ExternalPaths::Interest].push_back (Vector (nb_points));
150
+ for (size_t j = 0 ; j < nb_points; j++)
151
+ {
152
+ external_paths[ExternalPaths::Interest][i][j] = generated_paths[i][j];
153
+ }
154
+ }
155
+
156
+ generate_external_path_fx<<<m0, 1 >>> (d_paths, d_m0, d_N, d_T);
157
+ for (size_t i = 0 ; i < m0; i++)
158
+ {
159
+ generated_paths[i] = new double [nb_points];
160
+ cudaMemcpy (generated_paths[i], d_paths[i], nb_points * sizeof (double ), cudaMemcpyDeviceToHost);
161
+ external_paths[ExternalPaths::FX].push_back (Vector (nb_points));
162
+ for (size_t j = 0 ; j < nb_points; j++)
163
+ {
164
+ external_paths[ExternalPaths::FX][i][j] = generated_paths[i][j];
165
+ }
166
+ }
167
+
168
+ generate_external_path_equity<<<m0, 1 >>> (d_paths, d_m0, d_N, d_T);
169
+ for (size_t i = 0 ; i < m0; i++)
170
+ {
171
+ generated_paths[i] = new double [nb_points];
172
+ cudaMemcpy (generated_paths[i], d_paths[i], nb_points * sizeof (double ), cudaMemcpyDeviceToHost);
173
+ external_paths[ExternalPaths::Equity].push_back (Vector (nb_points));
174
+ for (size_t j = 0 ; j < nb_points; j++)
175
+ {
176
+ external_paths[ExternalPaths::Equity][i][j] = generated_paths[i][j];
177
+ }
178
+ }
179
+
180
+ for (size_t i = 0 ; i < m0; i++)
181
+ {
182
+ delete[] generated_paths[i];
183
+ }
184
+ delete[] generated_paths;
185
+
186
+ for (size_t i = 0 ; i < m0; i++)
187
+ {
188
+ cudaFree (d_paths[i]);
189
+ }
22
190
191
+ cudaFree (d_paths);
192
+ cudaFree (d_m0);
193
+ cudaFree (d_m1);
194
+ cudaFree (d_T);
195
+ cudaFree (d_N);
23
196
}
0 commit comments