Я правильно использую Deedle Series.map? - PullRequest
1 голос
/ 12 июня 2019

После некоторого тестирования в разных коллекциях я хотел посмотреть, какая из них будет работать лучше всего. Я протестировал массив, последовательность, список и серию из 1000000 точек, равномерно выбранных в диапазоне от 0,0 до 1,0. Затем я применяю их функцию .map к сигмоидальной функции:

let sigmoid x = 1. / (1. + exp(-x))

Затем я использую BenchmarkDotNet для расчета среднего времени исполнения и получаю то, что я считаю "безобразным" для Deedle.Series. Мне кажется, что Дидл действительно не «дружелюбен к карте». Я правильно все делаю?

// * Summary *

BenchmarkDotNet=v0.11.5, OS=Windows 7 SP1 (6.1.7601.0)
Intel Xeon CPU E5-1620 v3 3.50GHz, 1 CPU, 8 logical and 4 physical cores
Frequency=3410126 Hz, Resolution=293.2443 ns, Timer=TSC
.NET Core SDK=3.0.100-preview5-011568
  [Host]     : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT DEBUG  [AttachedDebugger]
  DefaultJob : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT


|             Method |        Mean |      Error |     StdDev |      Gen 0 |     Gen 1 |     Gen 2 | Allocated |
|------------------- |------------:|-----------:|-----------:|-----------:|----------:|----------:|----------:|
|              Array |    21.29 ms |  0.4217 ms |  0.9255 ms |   406.2500 |  406.2500 |  406.2500 |  15.26 MB |
|               List |   173.52 ms |  2.9243 ms |  2.7354 ms | 11250.0000 | 4500.0000 | 1500.0000 |  61.04 MB |
|                Seq |   127.90 ms |  2.5884 ms |  7.4267 ms | 36600.0000 |         - |         - | 183.11 MB |
|             Series | 1,751.04 ms | 37.6797 ms | 59.7640 ms | 99000.0000 | 6000.0000 | 6000.0000 | 603.31 MB |

1 Ответ

1 голос
/ 13 июня 2019

Я думаю, что ваши измерения, скорее всего, правильные.Ряд Deedle определенно добавляет заметные накладные расходы на массивы - это потому, что он также добавляет много дополнительных функций, связанных с обработкой пропущенных значений и всеми функциями, связанными с тем, что ряд является отображением значения ключа.

ЕслиВы делаете чисто числовые вычисления, которые не включают в себя грязные данные или данные с индексом, тогда вам, вероятно, следует использовать библиотеку матричных манипуляций или необработанные массивы.

Мои простые измерения с использованием #time следующие:

#time 
let rnd = System.Random()
let s = series [ for i in 0 .. 1000000 -> i, rnd.NextDouble() ]
let a = [| for i in 0 .. 1000000 -> rnd.NextDouble() |]

// ~950ms
let r = 1. / (1. + exp(-s))

// ~290ms
s |> Series.map (fun _ v -> 1. / (1. + exp(-v)))

// ~25ms
a |> Array.map (fun v -> 1. / (1. + exp(-v)))

Стоит отметить, что Series.map намного быстрее, чем выполнение последовательности двоичных операторов напрямую, потому что ему нужно создать только один новый экземпляр серии.

...