Программа Excel VBA работает только на 25% скорости
У меня на четырехъядерном ноутбуке Acer Aspire S3 работает программа VBA. Проблема в том, что он использует только 25% ЦП (остальные процессы вместе используют ~1%). Ноутбук работает под управлением Windows 8.0. Выпуск Excel 2013 (32-разрядная версия). Используется только 55% оперативной памяти, в то время как Excel использует половину из 55%.
Я думаю, может быть, используется только 25%, потому что Excel использует только одно ядро. Однако у меня нет ничего, чтобы поддержать эту теорию. Как я могу ускорить программу?
Благодарю.
5 ответов
Мне кажется, что программа, которую вы пытаетесь использовать, является однопоточной, то есть она может использовать только одно ядро, она не знает, что другие существуют. На самом деле нет конкретного способа ускорить этот процесс, кроме как купить процессор с более высокой тактовой частотой одного ядра или использовать программу, которая поддерживает многопоточность.
Все ниже относится к Excel 2007 и более ранним версиям. Согласно ссылке @Ƭᴇcʜιᴇ007, размещенной в комментариях выше, в Excel 2013 есть некоторая встроенная поддержка многопоточности. Тем не менее, предупреждение просто забыть об этом, если вы не являетесь опытным программистом, по-прежнему применяется.
К сожалению, VBA не поддерживает многопоточность, поэтому ваши вычисления VBA будут ограничены одним ядром вашего процессора.
Тем не менее, существует продвинутый метод обмана VBA для запуска нескольких потоков путем создания файлов VBscript и их одновременного выполнения. Это позволяет обойти проблему, запустив ваш код вне процесса Excel, и позволяет Windows управлять ресурсами, выделенными для разных потоков.
Тем не менее, заставить его работать, скорее всего, будет означать полное переосмысление логики вашего кода (т. Е. Вам придется выяснить, как разделить задачи таким образом, чтобы они выполнялись одновременно), что может очень хорошо быть невозможным для вашего проекта. Я никогда не реализовывал это сам, поэтому я не могу помочь вам с этим больше, чем рассказывать то, что я вам уже сказал.
Если вы хотите проникнуть в кроличью нору, то вот интересное сообщение в блоге, которое показывает пример того, как это делается. Имейте в виду: если вы не являетесь опытным программистом, вы можете также забыть об этой идее и просто признать, что VBA работает в одном потоке.
Другие ресурсы по переполнению стека для смелых:
https://stackoverflow.com/q/19159025/657668
https://stackoverflow.com/q/5721564/657668
Есть, конечно, другие способы оптимизировать код VBA без использования нескольких потоков. Не видя ваш код, невозможно сделать точные предложения, но вот пара обычных подозреваемых:
- Загрузите данные из вашего листа в массив для более быстрой обработки. Взаимодействия с рабочим листом являются основным узким местом в исполнении VBA, и их можно минимизировать, работая с массивами.
- Связанная проблема - Excel пересчитывает книгу после каждого изменения, внесенного в ячейку. Этого можно избежать, установив
Application.Calculation = xlManual
, Просто не забудьте установить его обратно вApplication.Calculation = xlAutomatic
перед выходом из вашего Sub.
Отказ от ответственности: это неправильный ответ, но я нахожу, что многим пользователям необходимо найти этот тип указаний вместе с другими ответами относительно использования только одного ядра, и моя репутация слишком низка, чтобы публиковать ее в качестве комментария.
Похоже, ваш VBA-скрипт использует только одно ядро, и это может быть хорошо!
Как уже упоминали другие в хороших ответах, я думаю, что важно знать другие аспекты этого вопроса, чтобы помочь вам найти подходящее решение. Итак, как вы ускоряете программу?
- 100% использование процессора в обзоре системы не означает, что ваша программа работает так быстро, как может: возможно, будет сделано много бесполезных вещей, попробуйте поискать "Оптимизация скорости VBA". Любая хорошая поисковая система даст вам несколько полезных ответов из сети Stack Exchange. Идите на время, потраченное на расчеты, а не на использование процессора.
- VBA в Excel не обязательно является лучшим инструментом для выполнения работы: для длительных вычислений, вычисляющих числа, может быть полезно экспортировать данные из Excel и использовать какую-то другую платформу, в зависимости от ваших навыков программирования. Есть очень много на выбор, некоторые прекрасно интегрируются с платформой Microsoft и имеют значительно лучшую достижимую производительность (выполнение бесполезных вещей также применимо и здесь).
- Запуск 100% CPU, вероятно, не даст вам 4-кратное увеличение скорости по сравнению с только 25%: в зависимости от того, насколько хорошо вы разбьете свои вычисления, вы можете добиться всего лишь 2-кратного повышения на 4 ядрах. Но есть случаи, которые приводят к почти 4-кратному увеличению на 4 ядрах - например, если вычисления, выполняемые в каждой строке, полностью независимы от любых других данных в вашей электронной таблице. Смотрите закон Амдала о Википедии.
- Возможно, не стоит пытаться использовать больше ядер: хотя это может быть полезно в некоторых случаях, сделать ваши вычисления более чем одним ядром может быть (и обычно бывает) на порядок сложнее, требуя некоторого тщательного опыта в методы программирования (см. этот вопрос для общего обзора).
- Бонус: Возможно, вам вообще не нужно ускорять вашу программу. Если расчет занимает, скажем, три минуты, а вы запускаете его только один раз в день, почему бы не подняться со стула немного и не напрячь свои жесткие кости? Вы рискуете потратить дни на настройку своей программы, чтобы иметь возможность запустить ее за две минуты тридцать, что окупается лишь в очень длительной перспективе. Хороший программист тратит свое время на оптимизацию только тогда, когда это действительно того стоит, так что пусть вас вдохновляют хорошие программисты:)
Как говорили другие, изначально VBA не является многопоточным. Если вы хотите ускорить работу, вы можете подумать о написании пользовательских функций (UDF) на другом языке.
Я бы порекомендовал вам ExcelDNA и использовать C# или VB.Net. Они очень просты в использовании, если вы уже знаете, как написать некоторый C#, и вы можете управлять многопоточностью в UDF.
Как уже говорили другие, многопоточность была бы ответом, но это не совсем выполнимое решение, и обновление до 64-битной системы имело бы незначительную разницу. Одна вещь, которую вы могли бы попытаться сделать, это повысить приоритет процесса, вы можете увидеть, как это сделать здесь.
Трудно сказать, ускорит ли это ваш сценарий или нет, поскольку в других местах программы может быть еще одно узкое место (например, чтение / запись с диска), но это, по крайней мере, даст Windows знать, что это более высокий приоритет, чем ваш. другие процессы.