Мотивация
У меня есть долговременная логическая функция, которая должна выполняться в массиве, и я хочу немедленно вернуться, если элемент в массиве удовлетворяет условию. Я хотел бы выполнить поиск параллельно и завершить другие потоки, когда первый завершенный поток возвращает правильный ответ.
Вопрос
Каков хороший способ реализовать функцию параллельного существования в F #? Поскольку моя цель - производительность, эффективное решение предпочтительнее простого или идиоматического.
Контрольный пример
Предположим, я хочу узнать, существует ли одно значение в массиве или нет. А функция сравнения (equals
) моделируется как вычислительно-дорогая:
open System.Diagnostics
open System.Threading
// Source at http://parallelpatterns.codeplex.com/releases/view/50473
let doCpuIntensiveOperation seconds (token:CancellationToken) throwOnCancel =
if (token.IsCancellationRequested) then
if (throwOnCancel) then token.ThrowIfCancellationRequested()
false
else
let ms = int64 (seconds * 1000.0)
let sw = new Stopwatch()
sw.Start()
let checkInterval = Math.Min(20000000, int (20000000.0 * seconds))
// Loop to simulate a computationally intensive operation
let rec loop i =
// Periodically check to see if the user has requested
// cancellation or if the time limit has passed
let check = seconds = 0.0 || i % checkInterval = 0
if check && token.IsCancellationRequested then
if throwOnCancel then token.ThrowIfCancellationRequested()
false
elif check && sw.ElapsedMilliseconds > ms then
true
else
loop (i + 1)
// Start the loop with 0 as the first value
loop 0
let inline equals x y =
doCpuIntensiveOperation 0.01 CancellationToken.None false |> ignore
x = y
Массив состоит из 1000 случайно сгенерированных элементов, и значение поиска гарантируется во 2-й половине массива (поэтому последовательный поиск должен проходить хотя бы половину массива):
let rand = new System.Random()
let m = 1000
let N = 1000000
let xs = [|for _ in 1..m -> rand.Next(N)|]
let i = rand.Next((m-1)/2, m-1);;
#time "on";;
let b1 = parallelExists (equals xs.[i]) xs;; // Parallel
let b2 = Array.exists (equals xs.[i]) xs;; // Sequential