Какой самый оптимальный способ применить ядро ​​к большому массиву в F #? - PullRequest
1 голос
/ 01 апреля 2020

У меня есть следующий код:

// reduce by 25x
let smallOutput = Array2D.init (output.GetLength(0) / 5) (output.GetLength(1) / 5) (fun _ _ -> Int32.MinValue)
let weights =
    array2D [|
        [| 1; 1; 1; 1; 1 |]
        [| 1; 3; 3; 3; 1 |]
        [| 1; 3; 5; 3; 1 |]
        [| 1; 3; 3; 3; 1 |]
        [| 1; 1; 1; 1; 1 |]
    |]
let weightsSum = 45
for y in [0 .. smallOutput.GetLength(0) - 1] do
    for x in [0 .. smallOutput.GetLength(1) - 1] do
        let mutable v = 0
        for i in [0 .. 4] do
            for j in [0 .. 4] do
                v <- v + weights.[j, i] * output.[y * 5 + j, x * 5 + i]

        smallOutput.[y, x] <- v / weightsSum

Он принимает большую матрицу (16k x 16k) и уменьшает ее в 25 раз при применении весов.

Я понимаю, что могу попытаться сделать это в Parallel.ForEach l oop, но мне интересно, есть ли что-нибудь встроенное в F #, которое в первую очередь позволило бы сделать это быстрее.

1 Ответ

0 голосов
/ 01 апреля 2020

Я не думаю, что вы можете многое сделать для дальнейшей оптимизации, если не считать суммирование уже при инициализации переменной smallOutput; то есть

let smallOutput = Array2D.init (output.GetLength(0) / 5) (output.GetLength(1) / 5) (fun y x -> 
    let mutable v = 0
    for i in [0 .. 4] do
        for j in [0 .. 4] do
            v <- v + weights.[j, i] * output.[y * 5 + j, x * 5 + i]
    v / weightsSum)

Дело в том, что вам нужно l oop для всех записей в большем массиве, нет способа обойти это. Если вы заранее знаете структуру весовой матрицы, например, что она симметрична c, вы можете использовать ее. Думаю, честно говоря, я не уверен, сколько из оптимизации, которая принесет.

...