Каков эффект "if false then()" в записи игрового поля "Компьютерный язык" F # Threadring?
Компьютерные игры Benchmarks Game Запись F # для Threadring содержит, казалось бы, бесполезную строку: if false then ()
. Когда я прокомментирую эту строку, программа работает намного быстрее (~ 2s против 55 секунд для ввода 50000000) и дает тот же результат. Как это работает? Почему эта линия там? Что именно делает компилятор с тем, что кажется нерабочим?
Код:
let ringLength = 503
let cells = Array.zeroCreate ringLength
let threads = Array.zeroCreate ringLength
let answer = ref -1
let createWorker i =
let next = (i+1)%ringLength
async { let value = cells.[i]
if false then ()
match value with
| 0 -> answer := i+1
| _ ->
cells.[next] <- value - 1
return! threads.[next] }
[<EntryPoint>]
let main args =
cells.[0] <- if args.Length>0 then int args.[0] else 50000000
for i in 0..ringLength-1 do
threads.[i]<-createWorker i
let result = Async.StartImmediate(threads.[0])
printfn "%d" !answer
0
Ответы
Ответ 1
Если выражение вычисления содержит if false then ()
, тогда асинхронный рабочий процесс будет переведен немного по-другому. В строке используется async.Combine
. Упрощенный код выглядит так:
async.Delay(fun () ->
value = cells.[i]
async.Combine
( async.Return(if false then ())
async.Delay(fun () ->
match value with (...) ) ))
Вставка переводов Combine
, потому что (потенциально) асинхронное вычисление, выполняемое циклом if
, должно сочетаться со следующим кодом. Теперь, если вы удалите if
, вы получите что-то вроде:
async.Delay(fun () ->
value = cells.[i]
match value with (...) ) ))
Разница в том, что теперь в функции, переданной в Delay
, выполняется намного больше работы.
EDIT: Я думал, что это вызвало разницу, потому что в коде вместо Async.Start
используется Async.StartImmediate
, но это, похоже, не так. На самом деле, я не понимаю, почему код использует асинхронные рабочие процессы вообще...
EDIT II.. Я не совсем уверен в Mono, но он определенно реплицируется в F # interactive - там версия с Combine
примерно в 4 раза медленнее (что и есть Я ожидаю, из-за накладных расходов функции).
Ответ 2
Я написал этот код изначально. Я не помню точной причины, по которой я добавил линию, но я предполагаю, что без нее оптимизатор будет делать то, что, как я думал, было вне духа тестовой игры. Причиной использования асинхронов в первую очередь является достижение продолжения хвостового вызова до следующего async (что делает его намного лучше, чем С# mono).
- Джомо