| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 | # StarPU --- Runtime system for heterogeneous multicore architectures.## Copyright (C) 2020       Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria## StarPU is free software; you can redistribute it and/or modify# it under the terms of the GNU Lesser General Public License as published by# the Free Software Foundation; either version 2.1 of the License, or (at# your option) any later version.## StarPU is distributed in the hope that it will be useful, but# WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.## See the GNU Lesser General Public License in COPYING.LGPL for more details.#import Libdlusing StarPU@target STARPU_CPU+STARPU_CUDA@codelet function black_scholes(data ::Matrix{Float64}, res ::Matrix{Float64}) :: Float32        widthn ::Int64 = width(data)            # data[1,...] -> S    # data[2,...] -> K    # data[3,...] -> r    # data[4,...] -> T    # data[4,...] -> sig    p ::Float64 = 0.2316419    b1 ::Float64 = 0.31938153    b2 ::Float64 = -0.356563782    b3 ::Float64 = 1.781477937    b4 ::Float64 = -1.821255978    b5 ::Float64 = 1.330274428        @parallel for i = 1:widthn                d1 ::Float64 = (log(data[1,i] / data[2,i]) + (data[3,i] + pow(data[5,i], 2.0) * 0.5) * data[4,i]) / (data[5,i] * sqrt(data[4,i]))        d2 ::Float64 = (log(data[1,i] / data[2,i]) + (data[3,i] - pow(data[5,i], 2.0) * 0.5) * data[4,i]) / (data[5,i] * sqrt(data[4,i]))                f ::Float64 = 0        ff ::Float64 = 0        s1 ::Float64 = 0        s2 ::Float64 = 0        s3 ::Float64 = 0        s4 ::Float64 = 0        s5 ::Float64 = 0        sz ::Float64 = 0                        ######## Compute normcdf of d1        normd1p ::Float64 = 0        normd1n ::Float64 = 0        boold1 ::Int64 = (d1 >= 0) + (d1 <= 0)                if (boold1 >= 2)            normd1p = 0.5            normd1n = 0.5        else            tmp1 ::Float64 = abs(d1)            f = 1 / sqrt(2 * M_PI)            ff = exp(-pow(tmp1, 2.0) / 2) * f            s1 = b1 / (1 + p * tmp1)            s2 = b2 / pow((1 + p * tmp1), 2.0)            s3 = b3 / pow((1 + p * tmp1), 3.0)            s4 = b4 / pow((1 + p * tmp1), 4.0)            s5 = b5 / pow((1 + p * tmp1), 5.0)            sz = ff * (s1 + s2 + s3 + s4 + s5)                    if (d1 > 0)                normd1p = 1 - sz # normcdf(d1)                normd1n = sz # normcdf(-d1)            else                normd1p = sz                normd1n = 1 - sz            end            end        ########                ######## Compute normcdf of d2        normd2p ::Float64 = 0        normd2n ::Float64 = 0        boold2 ::Int64 = (d2 >= 0) + (d2 <= 0)                if (boold2 >= 2)            normd2p = 0.5            normd2n = 0.5        else            tmp2 ::Float64 = abs(d2)            f = 1 / sqrt(2 * M_PI)            ff = exp(-pow(tmp2, 2.0) / 2) * f            s1 = b1 / (1 + p * tmp2)            s2 = b2 / pow((1 + p * tmp2), 2.0)            s3 = b3 / pow((1 + p * tmp2), 3.0)            s4 = b4 / pow((1 + p * tmp2), 4.0)            s5 = b5 / pow((1 + p * tmp2), 5.0)            sz = ff * (s1 + s2 + s3 + s4 + s5)                            if (d2 > 0)                normd2p = 1 - sz # normcdf(d2)                normd2n = sz # normcdf(-d2)            else                normd2p = sz                normd2n = 1 - sz            end        end        # normd1p = (1 + erf(d1/sqrt(2.0)))/2.0        # normd1n = (1 + erf(-d1/sqrt(2.0)))/2.0                # normd2p = (1 + erf(d2/sqrt(2.0)))/2.0        # normd2n = (1 + erf(-d2/sqrt(2.0)))/2.0                res[1,i] = data[1,i] * (normd1p) - data[2,i]*exp(-data[3,i]*data[4,i]) * (normd2p) # S * N(d1) - r*exp(-r*T) * norm(d2)        res[2,i] = -data[1,i] * (normd1n) + data[2,i]*exp(-data[3,i]*data[4,i]) * (normd2n) # -S * N(-d1) + r*exp(-r*T) * norm(-d2)            end    return 0endstarpu_init()function black_scholes_starpu(data ::Matrix{Float64}, res ::Matrix{Float64}, nslices ::Int64)    vert = StarpuDataFilter(STARPU_MATRIX_FILTER_VERTICAL_BLOCK, nslices)    @starpu_block let        dat_handle, res_handle = starpu_data_register(data, res)        starpu_data_partition(dat_handle, vert)        starpu_data_partition(res_handle, vert)                #Compute the price of call and put option in the res matrix        @starpu_sync_tasks for task in (1:nslices)            @starpu_async_cl black_scholes(dat_handle[task], res_handle[task]) [STARPU_RW, STARPU_RW]         end    end    return 0endfunction init_data(data, data_nbr);    for i in 1:data_nbr        data[1,i] = rand(Float64) * 100        data[2,i] = rand(Float64) * 100        data[3,i] = rand(Float64)        data[4,i] = rand(Float64) * 10        data[5,i] = rand(Float64) * 10    end    return dataend        function median_times(data_nbr, nslices, nbr_tests)    data ::Matrix{Float64} = zeros(5, data_nbr)    # data[1,1] = 100.0    # data[2,1] = 100.0    # data[3,1] = 0.05    # data[4,1] = 1.0    # data[5,1] = 0.2    res ::Matrix{Float64} = zeros(2, data_nbr)    exec_times ::Vector{Float64} = [0. for i in 1:nbr_tests]    for i = 1:nbr_tests                init_data(data, data_nbr)        tic()        black_scholes_starpu(data, res, nslices);        t = toq()        exec_times[i] = t    end    sort!(exec_times)    # println(data)    # println(res)        return exec_times[1 + div(nbr_tests - 1, 2)]endfunction display_times(start_nbr, step_nbr, stop_nbr, nslices, nbr_tests)    i = 1    open("black_scholes_times.dat", "w") do f         for data_nbr in (start_nbr : step_nbr : stop_nbr)            t = median_times(data_nbr, nslices, nbr_tests)            println("Number of data:\n$data_nbr\nTimes:\njl: $t\nC: $(mtc[i])\nGen: $(mtcgen[i])")            write(f, "$data_nbr $(t)\n")            i = i + 1        end    endend
 |