Ejemplo n.º 1
0
        private static void GeneratePaths(float[] paths, float r, float sigma, float dt, int numSims, int numTimesteps)
        {
            //
            int tid  = (BlockIndex.X * BlockDimension.X) + ThreadIndex.X;
            int step = GridDimension.X * BlockDimension.X;

            // Compute parameters
            float drift     = (r - (0.5f * sigma * sigma)) * dt;
            float diffusion = sigma * DeviceMath.Sqrt(dt);

            // Simulate the paths
            for (int i = tid; i < numSims; i += step)
            {
                // Current output index
                int output = i;

                // Simulate the path
                float s = 1.0f;
                for (int t = 0; t < numTimesteps; t++, output += numSims)
                {
                    s            *= DeviceMath.Exp(drift + (diffusion * NormalRNG.NextFloat()));
                    paths[output] = s;
                }
            }
        }
Ejemplo n.º 2
0
        private static void ComputeValue(float[] values, float[] paths, float optionSpotPrice, float optionStrikePrice, OptionType optionType, int numSims, int numTimesteps)
        {
            // Determine thread id
            int bid  = BlockIndex.X;
            int tid  = (BlockIndex.X * BlockDimension.X) + ThreadIndex.X;
            int step = GridDimension.X * BlockDimension.X;

            //
            float sumPayoffs = 0f;

            for (int i = tid; i < numSims; i += step)
            {
                //
                int pathIndex = i;

                // Compute the arithmatic average.
                float avg = 0f;
                for (int t = 0; t < numTimesteps; t++, pathIndex += numSims)
                {
                    avg += paths[pathIndex];
                }
                avg = avg * optionSpotPrice / numTimesteps;

                // Compute the payoff
                float payoff = DeviceMath.Max(0f, optionType == OptionType.Call ? avg - optionStrikePrice : optionStrikePrice - avg);

                // Accumulate payoff locally
                sumPayoffs += payoff;
            }

            // Reduce within the block
            // Perform first level of reduction:
            // - Write to shared memory
            int ltid = ThreadIndex.X;

            m_reductionScratchPad[ltid] = sumPayoffs;
            Kernel.SyncThreads();

            // Do reduction in shared mem
            for (int s = BlockDimension.X / 2; s > 0; s >>= 1)
            {
                if (ltid < s)
                {
                    m_reductionScratchPad[ltid] += m_reductionScratchPad[ltid + s];
                }

                Kernel.SyncThreads();
            }
            sumPayoffs = m_reductionScratchPad[0];

            // Store the result
            if (ThreadIndex.X == 0)
            {
                values[bid] = sumPayoffs;
            }
        }
Ejemplo n.º 3
0
        private static void Abs(int[] input, int[] output)
        {
            // Thread index
            int ThreadId = BlockDimension.X * BlockIndex.X + ThreadIndex.X;

            // Total number of threads in execution grid
            int TotalThreads = BlockDimension.X * GridDimension.X;

            // Loop over the test cases (input data), process them, and store the results for comparison against the reference values.
            for (int CaseIndex = ThreadId; CaseIndex < input.Length; CaseIndex += TotalThreads)
            {
                output[CaseIndex] = DeviceMath.Abs(input[CaseIndex]);
            }
        }
Ejemplo n.º 4
0
        private static void MultiplyAddGpu(float[] a, float[] b, float[] c, float[] d)
        {
            // Get the thread id and total number of threads
            int ThreadId     = BlockDimension.X * BlockIndex.X + ThreadIndex.X;
            int TotalThreads = BlockDimension.X * GridDimension.X;

            // Loop over the vectors 'a', 'b', and 'c', multiplying the elements from 'a' and 'b', adding the product to the element from 'c', then storing the result in 'd'.
            for (int ElementIndex = ThreadId; ElementIndex < a.Length; ElementIndex += TotalThreads)
            {
                // Within kernel methods, use the DeviceMath.MultiplyAdd(...) call instead of separate multiply/add steps whenever possible,
                // as this allows the GPU.NET compiler to emit the most-efficient (i.e., fastest-executing) code for your specific device.
                d[ElementIndex] = DeviceMath.MultiplyAdd(a[ElementIndex], b[ElementIndex], c[ElementIndex]);
                //d[ElementIndex] = (a[ElementIndex] * b[ElementIndex]) + c[ElementIndex];
            }
        }
Ejemplo n.º 5
0
        private static void BlackScholesGPUKernel(float[] callResult, float[] putResult, float[] stockPrice, float[] optionStrike, float[] optionYears, float riskFree, float volatility)
        {
            // Thread index
            int ThreadId = BlockDimension.X * BlockIndex.X + ThreadIndex.X;

            // Total number of threads in execution grid
            int TotalThreads = BlockDimension.X * GridDimension.X;

            // No matter how small execution grid is, or how many options we're processing,
            // by using this loop we'll get perfect memory coalescing
            for (int OptionIndex = ThreadId; OptionIndex < callResult.Length; OptionIndex += TotalThreads)
            {
                float s = stockPrice[OptionIndex];
                float x = optionStrike[OptionIndex];
                float t = optionYears[OptionIndex];

                // Calculate the square root of the time to option expiration, in years
                float SqrtT = DeviceMath.Sqrt(t);

                // Calculate the Black-Scholes parameters
                float d1 = (DeviceMath.Log(s / x) + (riskFree + 0.5f * volatility * volatility) * t) / (volatility * SqrtT);
                float d2 = d1 - volatility * SqrtT;

                // Plug the parameters into the Cumulative Normal Distribution (CND)
                float K1    = 1.0f / (1.0f + 0.2316419f * DeviceMath.Abs(d1));
                float CndD1 = RSQRT2PI * DeviceMath.Exp(-0.5f * d1 * d1) *
                              (K1 * (A1 + K1 * (A2 + K1 * (A3 + K1 * (A4 + K1 * A5)))));
                if (d1 > 0)
                {
                    CndD1 = 1.0f - CndD1;
                }

                float K2    = 1.0f / (1.0f + 0.2316419f * DeviceMath.Abs(d2));
                float CndD2 = RSQRT2PI * DeviceMath.Exp(-0.5f * d2 * d2) *
                              (K2 * (A1 + K2 * (A2 + K2 * (A3 + K2 * (A4 + K2 * A5)))));
                if (d2 > 0)
                {
                    CndD2 = 1.0f - CndD2;
                }

                // Calculate the discount rate
                float ExpRT = DeviceMath.Exp(-1.0f * riskFree * t);

                // Calculate the values of the call and put options
                callResult[OptionIndex] = s * CndD1 - x * ExpRT * CndD2;
                putResult[OptionIndex]  = x * ExpRT * (1.0f - CndD2) - s * (1.0f - CndD1);
            }
        }