Как уменьшить время выполнения программы

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

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

Рассмотрим следующие примеры.

Боль в пояснице уйдёт за 1 минуту!

Пример 2.2. Пусть имеется цикл следующей структуры (Pascal):

for у:—0 to 99 do for х:=0 to 99 do

В этом цикле операции умножения и обращения к элементу S[k] выполняются 10 000 раз. Оптимизируем цикл, используя, что 320 = 2 8 + 2 6 :

for х:=0 to 99 do begin

for у: =0 to 99 do ci[i+yj:—skl;

В результате вместо 10 000 операций умножения будут выполняться 200 операций сдвига, а их время приблизительно сравнимо со временем выполнения операции сложения. Обращение к элементу массива S[k] будет выполнено один раз.

Пример 2.3. Пусть имеется цикл, в теле которого реализовано сложное условие:

for к: =2 to п do begin

ifx[k]>yk then S: -S+y[kJ-x[kJ; if (x[k] yk then S: —S +y[kj-x[k] else

Источник: bstudy.net

Рекомендации по оптимизации срочного кода

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

В целом для улучшения срочного кода требуется следующее:

  • знание того, какие части программы должны выполняться быстро;
  • знание размера и скорости выполнения кода;
  • знание затрат на реализацию новых возможностей;
  • знание минимального объема работы, необходимого для выполнения задания.

Чтобы собрать сведения о производительности кода, можно использовать системный монитор (perfmon.exe).

Промахи кэша и ошибки страниц

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

Попадание в кэше ЦП позволяет программе выиграть 10–20 тактов. Попадание во внешнем кэше позволяет выиграть 20–40 тактов. Ошибка страницы может стоить миллион тактов (при условии, что процессор обрабатывает 500 миллионов инструкций в секунду и время 2 миллисекунды для сбоя страницы). Поэтому для оптимального выполнения программы необходимо написать код, который снизит число промахов кэша и ошибок страниц.

Как Правильно Дышать во время Бега? #shorts

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

  • Динамически выделенные связанные списки могут снизить производительность программы. При поиске элемента или переходе по списку до конца каждая пропущенная ссылка может пропустить кэш или вызвать сбой страницы. Реализация списка на основе простых массивов может выполняться быстрее из-за лучшего кэширования и меньшего количества ошибок страниц. Даже если вы допустите тот факт, что массив будет сложнее увеличить, он все равно может быть быстрее.
  • Хэш-таблицы, использующие динамически размещаемые связанные списки, могут ухудшить производительность. По мере расширения такие хэш-таблицы могут начать работать значительно медленнее. В конечном итоге, простой линейный поиск по массиву может быть фактически более быстрым (в зависимости от ситуации). Использование хэш-таблицы на основе массива (так называемого «закрытого хэширования») часто упускается из виду, которая часто имеет более высокую производительность.
Читайте также:
В какой программе лучше всего описывать бизнес процессы

Сортировка и поиск

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

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

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

Вот несколько общих советов по сортировке.

  • Используйте стандартную сортировку, чтобы свести к минимуму число ошибок.
  • Имеет смысл любая работа, которую можно выполнить предварительно для снижения сложности сортировки. Если однократная передача данных упрощает сравнение и уменьшает сортировку от O(n log n) до O(n), вы почти наверняка выйдете вперед.
  • Продумайте расположение ссылок для алгоритма сортировки и данных, которые планируется сортировать.

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

MFC и библиотеки классов

Библиотека Microsoft Foundation Classes (MFC) может значительно упростить написание кода. При написании срочного кода следует знать о накладных расходах, связанных с некоторыми классами. Проверьте код MFC, который используется срочным кодом, чтобы определить, соответствует ли он требованиям к производительности. В приведенном ниже списке указаны классы и функции MFC, о которых следует знать.

  • CString MFC вызывает библиотеку времени выполнения C для динамического CString выделения памяти. Как правило, это так же эффективно, CString как и любая другая динамически выделенная строка. Она также занимает дополнительные ресурсы для динамического размещения и удаления. Зачастую простой массив char в стеке может выполнять те же функции и быть более быстрым. Не используйте класс CString для хранения константной строки. Взамен рекомендуется использовать const char * . Любые операции, выполняемые с объектом CString , требуют некоторых дополнительных ресурсов. Использование строковых функций библиотеки времени выполнения может быть более быстрым.
  • CArray Обеспечивает CArray гибкость, которая отсутствует в обычном массиве, но это может не потребоваться вашей программе. Если известны определенные особенности, ограничивающие возможность использования массива, вместо этого можно использовать глобальный фиксированный массив. При применении объекта CArray используйте параметр CArray::SetSize , чтобы определить его размер и указать число элементов, на которое он может быть увеличен при перераспределении. В противном случае добавление элементов может вызвать частое перераспределение и копирование массива, что приведет к неэффективному использованию и фрагментации памяти. Кроме того, если вы вставляете элемент в массив, CArray перемещает последующие элементы в памяти и, возможно, потребуется увеличить массив. Эти действия могут вызвать промахи кэша и ошибки страниц. Если просмотреть код, который используется библиотекой MFC, то можно увидеть, что для повышения производительности в конкретном случае возможно создать более подходящий код. Так как CArray является шаблоном, можно, например, добавить специализации CArray для отдельных типов.
  • CList CList — это список, связанный вдвойне, поэтому вставка элементов выполняется быстро в начале, в конце и в известной позиции ( POSITION ) в списке. Поиск элементов по значению или индексу требует последовательного поиска, который, однако, может быть медленным, если список длинный. Если для кода не требуется список, связанный сдвояк, можно пересмотреть использование CList . Использование одного связанного списка экономит затраты на обновление другого указателя для всех операций и памяти для этого указателя. Дополнительная память не является большой, но это еще одна возможность для промахов кэша или ошибок страницы.
  • IsKindOf Эта функция может генерировать множество вызовов и получать доступ к памяти в разных областях данных, что приводит к неправильному месту ссылки. Это полезно для отладочной сборки (например, в вызове ASSERT), но старайтесь не использовать ее в сборке выпуска.
  • PreTranslateMessage Используйте PreTranslateMessage , когда для одного из деревьев окон требуются особые сочетания клавиш или необходимо добавить обработку сообщений в генератор сообщений. PreTranslateMessage изменяет сообщения об отправке MFC. При переопределении PreTranslateMessage делайте это только на необходимом уровне. Например, не нужно переопределять, CMainFrame::PreTranslateMessage если вас интересуют только сообщения, поступающие к дочерним элементам определенного представления. Вместо этого переопределите PreTranslateMessage для класса представления. Не обходить обычный путь диспетчеризации, используя PreTranslateMessage для обработки сообщений, отправляемых в любое окно. Используйте для этой цели оконные процедуры и схемы сообщений MFC.
  • OnIdle События простоя могут возникать в периоды, когда вы не ожидаете, например между WM_KEYDOWN событиями и WM_KEYUP . Возможно, для запуска кода более эффективным будет использование таймеров. Не заставляйте OnIdle вызываться повторно, создавая ложные сообщения или всегда возвращая TRUE из переопределения OnIdle , которое никогда не позволит потоку переходить в спящий режим. Таймер или отдельный поток может быть более правильным решением и в этом случае.
Читайте также:
В какой программе сделать афишу на телефоне

Общие библиотеки

Повторное использование кода желательно. Однако если вы собираетесь использовать чужой код, следует убедиться, что вы точно знаете, что он делает в тех случаях, когда производительность имеет решающее значение. Лучший способ понять это — пошаговое изучение исходного кода или измерение с помощью таких средств, как PView или Монитор производительности.

Кучи

Используйте несколько куч с осторожностью. Дополнительные кучи, созданные с помощью HeapCreate и HeapAlloc , позволяют управлять связанными наборами выделенной памяти и затем удалять их. Не выделяйте слишком много памяти. При использовании нескольких куч особое внимание уделите изначально выделенному объему памяти.

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

В некоторых случаях, тем не менее, использование кучи по умолчанию может ухудшить расположение ссылок. Используйте средство просмотра процессов, Spy++ или системный монитор, чтобы оценить эффект перемещения объектов между кучами.

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

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

Читайте также:
Лучшая программа для ведения домашней бухгалтерии на Андроид

Для мониторинга использования памяти можно также использовать счетчики производительности.

Потоки

Для задач, выполняемых в фоновом режиме, эффективная обработка простоя событий может быть более быстрой, чем использование потоков. В однопоточной программе легче понять расположение ссылок.

Потоки рекомендуется использовать, только если блокируемое уведомление операционной системы находится в корневом процессе фоновой работы. Потоки являются лучшим решением в таком случае, так как блокировать main поток в событии нецелесообразно.

Потоки также вызывают проблемы со взаимодействием. Каналом взаимодействия между потоками необходимо управлять с помощью списка сообщений или путем выделения и использования общей памяти. Управление каналом взаимодействия обычно требует синхронизации во избежание состояний гонки и взаимоблокировки. Такое усложнение легко может обернуться ошибками и проблемами с производительностью.

Небольшой рабочий набор

Чем меньше размер рабочих наборов, тем лучше расположение ссылок, меньше число ошибок страниц и больше попаданий в кэше. Рабочий набор процессов является наиболее точным показателем, который операционная система непосредственно предоставляет для оценки расположения ссылок.

  • Чтобы задать верхний и нижний пределы рабочего набора, используйте SetProcessWorkingSetSize .
  • Чтобы получить верхний и нижний пределы рабочего набора, используйте GetProcessWorkingSetSize .
  • Чтобы просмотреть размер рабочего набора, используйте Spy++.

Источник: learn.microsoft.com

Как уменьшить время работы программы — C#

Подскажите пожалуйста как уменьшить время работы программы на 0.5 секунд. int n1 = int.Parse(Console.ReadLine()); int[] a = new int[n1]; for (int i = 0; i < n1; i++) < a[i]=int.Parse(Console.ReadLine()); >int n2=int.Parse(Console.ReadLine()); int[] b=new int[n2]; for (int j=0; j < n2; j++) < b[j]=int.Parse(Console.ReadLine()); >Array.Sort(a); int k=0; for (int j=0; j < b.Length; j++) < for (int i=0; i < a.Length; i++) < if (b[j]==a[i]) < k++; break; >> > Console.WriteLine(k);

Код к задаче: «Как уменьшить время работы программы»

Листинг программы

Array.Sort(a); Array.Sort(b); int k = 0; int i = 0; int j = 0; do < if (a[i] < b[j]) < i++; >else < if (b[j] == a[i]) < k++; >j++; > > while (i != a.Length j != b.Length);

Источник: studassistent.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru