Как получить оптимизацию из «чистой функции» в C #?

Если вы изменили свой порт, вы получите такую ​​ошибку «com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Ошибка связи с каналом связи» Пожалуйста, проверьте номер вашего порта

14
задан Larsenal 1 September 2009 в 15:51
поделиться

7 ответов

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

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

Эта область будет приобретать все большее значение, поскольку массовые многоядерные машины станут менее дорогими и более распространенными. У нас есть долгосрочная цель исследования языка C #: найти способ использовать преимущества чистых функций (и нечистых, но «изолированных» функций) в языке, компиляторе и среде выполнения. Но это связано с множеством сложных проблем, проблем, относительно которых в промышленности и научных кругах нет единого мнения относительно наилучшего подхода. Лучшие умы думают об этом, но не ожидают каких-либо серьезных результатов в ближайшее время.

25
ответ дан 1 December 2019 в 07:12
поделиться

, если расчет был дорогостоящим, вы могли бы кэшировать результат в словаре?

    static Dictionary<int, int> cache = new Dictionary<int, int>();
    public static int AddOne(int x)
    {
        int result;
        if(!cache.TryGetValue(x, out result))
        {
            result = x + 1;
            cache[x] = result;
        }
        return result;
    }

конечно, поиск в словаре в этом случае дороже, чем add :)

Есть еще один гораздо более крутой способ функциональной мемоизации, объясненный здесь Весом Дайером: http: // blogs.msdn.com/wesdyer/archive/2007/01/26/function-memoization.aspx - если вы сделаете МНОГО этого кеширования, то его функция Memoize может сэкономить вам много кода ...

8
ответ дан 1 December 2019 в 07:12
поделиться
2
ответ дан 1 December 2019 в 07:12
поделиться

Метод, который вам нужен, - это мемоизация : кэшировать результаты выполнения, привязанные к аргументам, переданным в функцию, в массиве или словаре. Среды выполнения не склонны применять его автоматически, хотя, безусловно, бывают случаи, когда они применялись бы. Ни C #, ни .NET не применяют мемоизацию автоматически. Вы можете реализовать мемоизацию самостоятельно - это довольно просто, но это обычно полезно только для более медленных чистых функций, где вы склонны повторять вычисления и где у вас достаточно памяти.

2
ответ дан 1 December 2019 в 07:12
поделиться

Это вероятно, будет встроен (также известен как встроенное расширение ) компилятором ...

Просто убедитесь, что вы скомпилировали свой код с установленным флагом «Оптимизировать код» (в VS: свойства проекта / вкладка сборки / Оптимизация Код)


Еще вы можете кэшировать результаты (также известные как мемоизация ). Однако из-за вашей логики поиска существует огромный начальный удар по производительности, поэтому это интересно только для медленных функций (то есть не для добавления int).

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


Насколько я понимаю, если время выполнения понял функциональную чистоту это может оптимизировать выполнение так, чтобы возвращаемые значения не должны быть пересчитано.

В вашем примере среда выполнения БУДЕТ вычислять результат, если x не известен во время компиляции. В этом случае ваш код будет дополнительно оптимизирован за счет использования сворачивания констант

1
ответ дан 1 December 2019 в 07:12
поделиться

Как компилятор мог это сделать? Как узнать, какие значения x будут переданы во время выполнения?

и re: другие ответы, в которых упоминается встраивание ... Насколько я понимаю, встраивание (в качестве оптимизации) оправдано для небольших функций, которые используются только один раз (или очень несколько раз ...) не потому, что у них нет побочных эффектов ...

0
ответ дан 1 December 2019 в 07:12
поделиться

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

AddOne(5);

AddOne может быть встроен:

5 + 1;

Распространение констант может затем упростить выражение:

6;

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

Знание того, что AddOne () не имеет побочных эффектов, может также позволить компилятору выполнить общее исключение подвыражения , так что:

AddOne(3) + AddOne(3)

может быть преобразовано в:

int x = AddOne(3);
x + x;

или путем уменьшения силы , даже:

2*AddOne(3);

Нет никакого способа дать команду компилятору C # JIT выполнить эти оптимизации; оптимизирует по своему усмотрению. Но он довольно умен, и вы должны чувствовать себя комфортно, полагаясь на него, чтобы выполнять такого рода преобразования без вашего вмешательства.

0
ответ дан 1 December 2019 в 07:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: