0
我正在与fsi.exe的两个版本相同的F#代码,我可以在我的FSharp-2.0.0.0找到相同的代码安装:巨大的性能差异运行F#的FSI 4.0.30319.1和2.0.0.0
C:\Program Files\FSharp-2.0.0.0\bin\fsi.exe - Microsoft (R) F# 2.0 Interactive build 2.0.0
C:\Program Files\FSharp-2.0.0.0\v4.0\bin\fsi.exe - Microsoft (R) F# 2.0 Interactive build 4.0.30319.1
我发现,在2.0.0.0版本上,相同的代码运行速度快了三倍。这有意义吗?有什么搞砸了我的环境或可能的代码?
顺便提一下,我尝试使用v4.0 build的原因是为了能够使用TPL并比较我的代码的顺序和并行实现。当我的并行执行比顺序执行慢得多时,经过大量的头痛之后,我意识到并行版本是在不同的fsi.exe下运行的,而当我意识到代码的相同(顺序)版本要慢得多在版本4.0下。
预先感谢任何帮助
IS
代码:
module Options
//Gaussian module is from http://fssnip.net/3g, by Tony Lee
open Gaussian
//The European Option type
type EuropeanOption =
{StockCode: string
StockPrice: float
ExercisePrice: float
NoRiskReturn: float
Volatility: float
Time: float
}
//Read one row from the file and return a European Option
//File format is:
//StockCode<TAB>StockPrice,ExercisePrice,NoRiskReturn,Volatility,Time
let convertDataRow(line:string) =
let option = List.ofSeq(line.Split('\t'))
match option with
| code::data::_ ->
let dataValues = (data.Split(','))
let euopt = {StockCode = code;
StockPrice = float (dataValues.[0]);
ExercisePrice = float (dataValues.[1]);
NoRiskReturn = float (dataValues.[2]);
Volatility = float (dataValues.[3]);
Time = float (dataValues.[4])
}
euopt
| _ -> failwith "Incorrect Data Format"
//Returns the future value of an option.
//0 if excercise price is greater than the sum of the stock price and the calculated asset price at expiration.
let futureValue sp ep nrr vol t =
//TODO: Is there no better way to get the value from a one-element sequence?
let assetPriceAtExpiration = sp+sp*nrr*t+sp*sqrt(t)*vol*(Gaussian.whiteNoise |> Seq.take 1 |> List.ofSeq |> List.max)
[0.0;assetPriceAtExpiration - ep] |> List.max
//Sequence to hold the values generated by the MonteCarlo iterations
//50,000 iterations is the minimum for a good aprox to the Black-Scholes equation
let priceValues count sp ep nrr vol t =
seq { for i in 1..count
-> futureValue sp ep nrr vol t
}
//Discount a future to a present value given the risk free rate and the time in years
let discount value noriskreturn time =
value * exp(-1.0*noriskreturn*time)
//Get the price for a European Option and a given number of Monte Carlo iterations (use numIters >= 50000)
let priceOption europeanOption numIters =
let futureValuesSeq = priceValues numIters europeanOption.StockPrice europeanOption.ExercisePrice europeanOption.NoRiskReturn europeanOption.Volatility europeanOption.Time
//The simulated future value is just the average of all the MonteCarlo runs
let presentValue = discount (futureValuesSeq |> List.ofSeq |> List.average) europeanOption.NoRiskReturn europeanOption.Time
//Return a list of tuples with the stock code and the calculated present value
europeanOption.StockCode + "_to_" + string europeanOption.Time + "_years \t" + string presentValue
module Program =
open Options
open System
open System.Diagnostics
open System.IO
//Write to a file
let writeFile path contentsArray =
File.WriteAllLines(path, contentsArray |> Array.ofList)
//TODO: This whole "method" is sooooo procedural.... is there a more functional way?
//Unique code for each run
//TODO: Something shorter, please
let runcode = string DateTime.Now.Month + "_" + string DateTime.Now.Day + "_" + string DateTime.Now.Hour + "_" + string DateTime.Now.Minute + "_" + string DateTime.Now.Second
let outputFile = @"C:\TMP\optionpricer_results_" + runcode + ".txt"
let statsfile = @"C:\TMP\optionpricer_stats_" + runcode + ".txt"
printf "Starting"
let mutable stats = ["Starting at: [" + string DateTime.Now + "]" ]
let stopWatch = Stopwatch.StartNew()
//Read the file
let lines = List.ofSeq(File.ReadAllLines(@"C:\tmp\9000.txt"))
ignore(stats <- "Read input file done at: [" + string stopWatch.Elapsed.TotalMilliseconds + "]"::stats)
printfn "%f" stopWatch.Elapsed.TotalMilliseconds
//Build the list of European Options
let options = lines |> List.map convertDataRow
ignore(stats <- ("Created Options done at: [" + string stopWatch.Elapsed.TotalMilliseconds + "]")::stats)
printfn "%f" stopWatch.Elapsed.TotalMilliseconds
//Calculate the option prices
let results = List.map (fun o -> priceOption o 50000) options
ignore(stats <- "Option prices calculated at: [" + string stopWatch.Elapsed.TotalMilliseconds + "]"::stats)
printfn "%f" stopWatch.Elapsed.TotalMilliseconds
//Write results and statistics
writeFile outputFile results
ignore(stats <- "Output file written at: [" + string stopWatch.Elapsed.TotalMilliseconds + "]"::stats)
ignore(stats <- "Total Ellapsed Time (minus stats file write): [" + string (stopWatch.Elapsed.TotalMilliseconds/60000.0) + "] minutes"::stats)
printfn "%f" stopWatch.Elapsed.TotalMilliseconds
writeFile statsfile (stats |> List.rev)
stopWatch.Stop()
ignore(Console.ReadLine())
如果您需要任何帮助,您将需要发布代码 - 我们不是精神病患者 –
尝试在v4上使用'ngen'。看起来很奇怪,但有可能它不是'原始'。 –
如果使用'fsc.exe'编译代码,您是否也会看到类似的差异? –