Когда следует использовать библиотеку линейной алгебры, такую ​​как Math.NET

Я не уверен, что есть один правильный ответ на вопрос, но здесь мы идем. Хотя многочисленные количественные проблемы могут быть сформулированы в форме линейной алгебры, по моему ограниченному опыту, из-за ограниченного опыта есть накладные расходы на производительность для простых операций при использовании Math.NET над написанием эквивалентных операций над необработанными массивами.

В качестве тестового примера я написал код для вычисления расстояния между вектором и ближайшим вектором в списке с тремя версиями: работа с массивами, работающими на плотных векторах и работающими на плотных векторах с провайдером MKL. Работа над массивами выполнялась примерно в 4 раза быстрее, чем на векторах, и в 3 раза быстрее, чем при использовании поставщика MKL.

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

Итак, мой вопрос таков: мне кажется, что использование абстракций более высокого уровня происходит за счет производительности. Это вообще дело, или есть ситуации (например, разреженные матрицы для экземпляров), где ожидается, что использование Math.NET будет превосходить операции, написанные вручную на массивах?

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

Любой свет, когда это хорошая идея использовать библиотеку против того, когда вы будете качать самостоятельно, будет оценен!

Ответ 1

Отказ от ответственности: я поддерживаю Math.NET Numerics.

Основное значение, которое предлагает инструментарий, например, Math.NET Numerics, - это производительность разработчика, особенно для тех, кто не имеет кандидата наук по этому вопросу, которому было бы трудно или тратить много времени на реализацию этих иногда довольно задействованные алгоритмы, возможно, плохо - вместо того, чтобы тратить время на их актуальную проблему.

Тогда есть вероятность, что необходимые вам функции уже были использованы другими. Некоторые из них, возможно, уже обнаружили и указали некоторые проблемы и внесли свои улучшения. Больше пользователей помогает улучшить качество и надежность кода. К сожалению, это также приводит к основному недостатку: Он также делает код более общим, что часто делает его менее эффективным, чем узкоспециализированная реализация, выполняющая именно то, что вам нужно.

Это все так же, как и код Cody Grey: используйте его, если он работает и достаточно быстро, иначе либо исправьте его, либо заставите его работать (и быстро), выберите другой инструментарий, который работает, или реализуйте именно то, что вам нужно сам. К счастью для Math.NET Numerics есть еще несколько вариантов, см. Ниже.

Таким образом, я согласен с вашим заключением: если вам действительно не нужны какие-либо сложные операции, не работайте с очень большими данными, но производительность важна, нет ничего плохого в использовании массивов или другой структуры данных напрямую (особенно в F #, где я лично буду рассматривать исходную структуру исходных данных чаще, чем в С#). Конечно, это связано с тем, что вы теряете удобство и риск того, что, когда вы начнете больше операций после завершения, вы можете перепрограммировать инструментарий. В конце концов, это также зависит от того, насколько это важно для вашего проекта, и можете ли вы тратить ресурсы и время на сохранение своего собственного математического кода.

Тем не менее, по моему собственному опыту, часто бывает преимуществом владеть кодом (чтобы вы могли вносить изменения, вступать в силу немедленно) и держать его простым, сосредоточенным (так что он делает именно то, что вам нужно, и только это).

Специфические для Math.NET Numerics

  • Очень конкретная управляемая реализация всегда может превзойти общую управляемую реализацию. Однако наша управляемая реализация не должна быть величинами медленнее, чем любые управляемые альтернативы. В конце концов, наши алгоритмы работают непосредственно на массивах, а также внутри (если их правильно оптимизировать). Если альтернативный алгоритм работает намного быстрее, кажется, что мы лучше заменим нашу реализацию этой альтернативой, поэтому, пожалуйста, сообщите нам об этом (или еще лучше внесите изменения).
  • Если вам удастся найти путь, в котором мы можем и используем собственный поставщик, такой как MKL, и вы имеете дело с большими данными, я ожидал бы, что Math.NET будет величинами быстрее, несмотря на более высокий уровень абстракции.
  • Не все кодовые пути в Math.NET Numerics оптимизированы одинаково, или используют собственные поставщики. В последние несколько второстепенных версий была поставлена ​​большая работа по линейной алгебре, поэтому мы становимся лучше, но медленно; впереди еще много работы (особенно для редких типов). Возможно, вы попали в какой-то трудно оптимизированный путь в вашем случае. Итак, я действительно очень заинтересован в вашем примере кода, чтобы мы могли работать в этом конкретном случае.

Советы по математике в численном выражении Math.NET

  • Использовать собственный провайдер
  • Немного экспериментируйте с параметрами распараллеливания в классе Control (но обратите внимание, что мы поняли, что реализация параллелизма до версии 2.4 была довольно плоха и планировала полностью ее заменить в версии 2.5. )
  • Старайтесь избегать доступа к любому At/indexer при реализации собственных операций, но напрямую обращайтесь к необработанному массиву (смотрите .Storage)
  • Многие операции позволяют указывать вектор/матрицу результатов, которая иногда может быть даже такой же, как один из операндов (на месте). Избегает создания нового массива в каждой операции и, таким образом, снижает давление памяти, если вы имеете дело с очень большими данными. К сожалению, также сделать код уродливым.