/* Program to compute swaption portfolio using NVIDIA CUDA */ #include #include // parameters for nVidia device execution #define BLOCK_SIZE 64 #define GRID_SIZE 64 // parameters for LIBOR calculation #define NN 80 #define NMAT 40 #define L2_SIZE 3280 //NN*(NMAT+1) #define NOPT 15 #define NPATH 4096 // constant data for swaption portfolio: stored in device memory, // initialised by host and read by device threads __constant__ int N, Nmat, Nopt, maturities[NOPT]; __constant__ float delta, swaprates[NOPT], lambda[NN]; /* Monte Carlo LIBOR path calculation */ __device__ void path_calc(float *L, float *z) { int i, n; float sqez, lam, con1, v, vrat; for(n=0; n=0; n--) { v1 = 0.0; for (i=N-1; i>n; i--) { v1 += lambda[i-n-1]*L2[i+(n+1)*N]*L_b[i]; faci = __fdividef(delta,1.0+delta*L2[i+n*N]); L_b[i] = L_b[i]*__fdividef(L2[i+(n+1)*N],L2[i+n*N]) + v1*lambda[i-n-1]*faci*faci; } } } /* calculate the portfolio value v, and its sensitivity to L */ /* hand-coded reverse mode sensitivity */ __device__ float portfolio_b(float *L, float *L_b) { int m, n; float b, s, swapval,v; float B[NMAT], S[NMAT], B_b[NMAT], S_b[NMAT]; b = 1.0; s = 0.0; for (m=0; m=0; m--) { n = m + Nmat; B_b[m] += delta*S_b[m]; L_b[n] = -B_b[m]*B[m]*__fdividef(delta,1.0+delta*L[n]); if (m>0) { S_b[m-1] += S_b[m]; B_b[m-1] += __fdividef(B_b[m],1.+delta*L[n]); } } // apply discount // b = 1.0; for (n=0; n= 1) break; } if (dev == deviceCount) { fprintf(stderr, "There is no device supporting CUDA.\n"); exit(EXIT_FAILURE); } else CUDA_SAFE_CALL(cudaSetDevice(dev)); CUT_SAFE_CALL( cutCreateTimer(&hTimer) ); for (i=0; i>>(d_v); CUT_CHECK_ERROR("Pathcalc_Portfolio_kernelGPU2() execution failed\n"); CUDA_SAFE_CALL( cudaThreadSynchronize() ); // Read back GPU results and compute average CUDA_SAFE_CALL( cudaMemcpy(h_v, d_v, sizeof(float)*NPATH, cudaMemcpyDeviceToHost) ); CUT_SAFE_CALL( cutStopTimer(hTimer) ); gpuTime = cutGetTimerValue(hTimer); v = 0.0; for (i=0; i>>(d_v,d_Lb); CUT_CHECK_ERROR("Pathcalc_Portfolio_kernelGPU() execution failed\n"); CUDA_SAFE_CALL( cudaThreadSynchronize() ); // Read back GPU results and compute average CUDA_SAFE_CALL( cudaMemcpy(h_v, d_v, sizeof(float)*NPATH, cudaMemcpyDeviceToHost) ); CUDA_SAFE_CALL( cudaMemcpy(h_Lb, d_Lb, sizeof(float)*NPATH, cudaMemcpyDeviceToHost) ); CUT_SAFE_CALL( cutStopTimer(hTimer) ); gpuTime = cutGetTimerValue(hTimer); v = 0.0; for (i=0; i