Моя головная боль на 32 бита является теперь мигренью на 64 бита?!? (или.NET на 64 бита проблемы Времени выполнения CLR)

Вам нужно поставить один } до того, как вы начнете метод public static String encrypt(String dot, SecretKey secretKey), то есть после окончания цикла for

9
задан Community 23 May 2017 в 12:01
поделиться

8 ответов

Я не забываю слышать проблему от канала IRC, который я часто посещаю. Это оптимизирует далеко временную копию в этом экземпляре:

EventHandler temp = SomeEvent;
if(temp != null)
{
    temp(this, EventArgs.Empty);
}

Откладывание состояния состязания в и порождение потенциальных исключений нулевой ссылки.

3
ответ дан 4 December 2019 в 21:51
поделиться

Я не настолько знаком с 64-разрядными проблемами, но у меня действительно есть один комментарий:

Мы должны забыть о маленькой эффективности, сказать приблизительно 97% времени: преждевременная оптимизация является корнем всего зла. - Donald Knuth

-1
ответ дан 4 December 2019 в 21:51
поделиться

Вы упомянули проблемы портирования, это - те, чтобы касаться в. Я (очевидно), не знаю, что Ваше приложение, но пытающийся пересмотреть JIT часто является полной пустой тратой времени. У людей, которые пишут JIT, есть близкое понимание x86/x64 архитектуры кристалла, и во всей вероятности знают то, что работает лучше и что работает хуже, чем, вероятно, кто-либо еще на планете.

Да, возможно, что у Вас есть угловой случай, который отличается и уникален, но если бы Вы "в процессе записи нового приложения", затем я не волновался бы о JIT-компиляторе. Там вероятно глупый цикл, которого можно избежать где-нибудь, который купит Вас 100x повышение производительности, которое Вы получите от попытки пересмотреть JIT. Напоминает мне о проблемах, что мы столкнулись с записью нашего ORM, мы будем смотреть на код и думать, что могли настроить несколько машинных команд из него..., конечно, код затем ушел и соединился с сервером базы данных по сети, таким образом, мы обрезали микросекунды от процесса, который был ограничен миллисекундами где-то в другом месте.

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

1
ответ дан 4 December 2019 в 21:51
поделиться

Большую часть времени Visual Studio и компилятор делают довольно хорошее задание сокрытия проблем от Вас. Однако я знаю об одной основной проблеме, которая может возникнуть, если Вы устанавливаете свое приложение, чтобы автоматически обнаружить платформу (x86 по сравнению с x64) и также иметь какие-либо зависимости от третьей стороны на 32 бита dlls. В этом случае на платформах на 64 бита это попытается назвать dlls использованием конвенций на 64 бита и структур, и это просто не будет работать.

1
ответ дан 4 December 2019 в 21:51
поделиться

Об ответе Quibblesome:

Я попытался запустить следующий код в своей Windows 7 x64 в Режим выпуска без отладчика, и исключение NullReferenceException никогда не генерировалось .

using System;
using System.Threading;

namespace EventsMultithreadingTest
{
    public class Program
    {
        private static Action<object> _delegate = new Action<object>(Program_Event);
        public static event Action<object> Event;

        public static void Main(string[] args)
        {
            Thread thread = new Thread(delegate()
                {
                    while (true)
                    {
                        Action<object> ev = Event;

                        if (ev != null)
                        {
                            ev.Invoke(null);
                        }
                    }
                });
            thread.Start();

            while (true)
            {
                Event += _delegate;
                Event -= _delegate;
            }
        }

        static void Program_Event(object obj)
        {
            object.Equals(null, null);
        }
    }
}
1
ответ дан 4 December 2019 в 21:51
поделиться

Я считаю, что 64 JIT не полностью разработан / портирован для использования преимуществ таких процессоров с 64-битной архитектурой, поэтому у него есть проблемы, вы можете получить «эмулируемое» поведение ваших сборок, что может вызвать проблемы и непредвиденное поведение. Я бы рассмотрел случаи, когда этого можно было бы избежать, и / или, возможно, посмотреть, есть ли хороший быстрый компилятор C ++ 64 для написания критических по времени вычислений и алгоритмов. Но даже если у вас есть трудности с поиском информации или у вас нет времени читать скрытый код, я вполне уверен, что перенос тяжелых вычислений за пределы управляемого кода уменьшит любые проблемы, которые могут у вас возникнуть, и повысит производительность [отчасти уверен, что вы уже делаете это но просто чтобы упомянуть :)]

0
ответ дан 4 December 2019 в 21:51
поделиться

Профилировщик не должен существенно влиять на ваши временные результаты. Если накладные расходы профилировщика действительно «значительны», то вы, вероятно, не сможете выжать из своего кода намного больше скорости, и вам следует подумать о поиске узких мест в вашем оборудовании (диск, ОЗУ или ЦП?) И модернизация. (Похоже, вы ограничены процессором, так что с этого и начните)

В общем, .net и JIT освобождают вас от большинства проблем с переносом 64-битной версии. Как вы знаете, есть эффекты, связанные с размером регистров (изменения использования памяти, маршалинг в машинный код, необходимость того, чтобы все части программы были собственными 64-битными сборками) и некоторые различия в производительности (большая карта памяти, больше регистров, более широкие шины. и т. д.), поэтому я не могу рассказать вам больше, чем вы уже знаете по этому поводу. Другие проблемы, которые я видел, связаны с ОС, а не с C # - например, теперь существуют разные кусты реестра для 64-битных приложений и приложений WOW64, поэтому некоторые обращения к реестру должны быть написаны осторожно.

Обычно плохая идея - беспокоиться о том, что JIT будет делать с вашим кодом, и пытаться настроить его, чтобы он работал лучше, потому что JIT, вероятно, изменится с .net 4, 5 или 6, и ваши "оптимизации" могут превратиться в неэффективность или, что еще хуже, ошибки.Также имейте в виду, что JIT компилирует код специально для процессора, на котором он работает, поэтому потенциально улучшение на вашем ПК для разработки может не быть улучшением на другом ПК. То, что вам сходит с рук при использовании сегодняшнего JIT на сегодняшнем CPU, может укусить вас через годы, когда вы что-то обновите.

В частности, вы цитируете «свойства не встроены в x64». К тому времени, когда вы пройдете всю свою кодовую базу, превратив все свои свойства в поля, вполне может появиться новая JIT для 64-битной версии, которая выполняет встроенные свойства. В самом деле, он вполне может работать лучше, чем ваш "обходной" код. Позвольте Microsoft оптимизировать это для вас.

Вы правильно указываете, что ваш профиль памяти может измениться. Таким образом, вам может потребоваться больше оперативной памяти, более быстрые диски для виртуальной памяти и большие кеши ЦП. Все проблемы с оборудованием. Возможно, вы сможете уменьшить эффект, используя (например) Int32, а не int, но это может не иметь большого значения и потенциально может нанести ущерб производительности (поскольку ваш процессор может обрабатывать собственные 64-битные значения более эффективно, чем 32-битные значения половинного размера ).

Вы говорите, что «время запуска может быть больше», но это кажется неуместным для приложения, которое, по вашему мнению, работает часов при 100% ЦП.

Так что вас действительно беспокоит? Возможно, рассчитайте время своего кода на 32-битном ПК, а затем время, когда он выполняет ту же задачу на 64-битном ПК. Есть ли разница в полчаса за 4 часа бега? Или разница всего 3 секунды? Или 64-битный ПК действительно быстрее? Может быть, вы ищете решения проблем, которых не существует.

Итак, вернемся к обычному, более общему совету. Профиль и время для выявления узких мест.Посмотрите на применяемые вами алгоритмы и математические процессы и попробуйте улучшить / заменить их более эффективными. Убедитесь, что ваш многопоточный подход помогает, а не вредит вашей производительности (т. Е. Предотвращается ожидание и блокировки). Попробуйте уменьшить выделение / освобождение памяти - например, повторно использовать объекты, а не заменять их новыми. Постарайтесь уменьшить использование частых вызовов функций и виртуальных функций. Переключитесь на C ++ и избавьтесь от накладных расходов, связанных со сборкой мусора, проверкой границ и т. Д., Которые накладывает .net. Хм. Ничего из этого не имеет отношения к 64-битной версии, не так ли?

0
ответ дан 4 December 2019 в 21:51
поделиться

Особенно неприятная проблема производительности в .NET связана с плохим JIT:

https://connect.microsoft.com/VisualStudio/feedback/details/93858/struct-methods-should-be-inlined?wa=wsignin1.0

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

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

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

Я перешел на использование Eigen в C++: он абсолютно великолепен, дает читаемый код и высокую производительность; тонкая обертка C++/CLI затем обеспечивает связь между вычислительным движком и миром .NET.

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

Так, например, если P - матрица, то этот тип вещей просто работает:

1.0 /  (P.transpose() * P).diagonal().sum();

... который не выделяет временно транспонированный вариант P, и не вычисляет все произведение матрицы, а только те поля, которые ему нужны.

Так что, если вы можете работать в Full Trust - просто используйте C++ через C++/CLI, это работает намного лучше.

4
ответ дан 4 December 2019 в 21:51
поделиться