f# - Why do prints to console get mixed up when doing parallel computations? -
while running code performs parallel computations output becomes garbled: different messages mixed up. here sample:
iteration 1 iteration iteration 23 of 19 - calculating p&l test window ending @ 10/28/1968 12:00:00 of iteration 4 iteration of iteration 5 iteration iteration 19 - calculating p&l test window ending @ of 19 - calculating p&l test window ending @ 5/29/1974 12:00:00 6 of 878/18/1971 12:00:00 am19 - calculating p&l test window ending @ 3/4/1977 12:00:00 of 19 of of 19 - calculating p&l test window ending @ 6/25/1985 12:00:00
when running same program sequentially console output comes out nice, no garbling.
printing console done function:
let windowtraintest (comm: communication) critfoo count (model: imodel) (assets: assets) (paramlist: parameters list) = // deleted code here if comm = verbose let msg1 = sprintf "\nwindowtraintestpandl: first date: %a, last date: %a\nbest criterion: %.2f\n" fdate ldate bestcriterion let msg2 = sprintf "best parameters: %a\n" bestparameters printfn "%s" <| msg1 + msg2 (pandl, wgts), bestparameters, ( ["criterion", bestcriterion] |> map.oflist, ["firstdate", fdate; "lastdate", ldate] |> map.oflist )
parallelization done portion of program:
let pseqmapi f (xs: seq<'t>) = xs |> pseq.mapi f let traintest n (trainsize, fullsize) = let takenassets = assets |> assets.take (min fullsize len) lastdate takenassets |> printfn "\niteration %d of %d - calculating p&l test window ending @ %a\n" (i + 1) n paramlist |> windowtraintest comm' critfoo trainsize model takenassets let maptraintest (initsizes: (int * int) list) = let f = traintest initsizes.length match calctype | pseq -> initsizes |> pseqmapi f |> list.ofseq | _ -> initsizes |> seq.mapi f |> list.ofseq
is there way avoid kind of behavior, example flushing message console?
parallel computations run on different threads, , if 1 thread interrupted in middle of printfn
, second thread runs printfn
before first thread gets run again, outputs interleaved.
the simplest way deal create new function use lock
keyword around printfn
invocations:
let lockobj = new obj() let lockedprintfn msg = lock lockobj (fun _ -> printfn msg)
then replace printfn
calls lockedprintfn
, should serialized output you're expecting. performance suffer little since threads spending time waiting printfn lock, long computations take longer time spent printing output, shouldn't notice slightly-slower performance.
Comments
Post a Comment