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

В приведенном коде была создана тестовая реализация для обработки массива <i>vec01</i>. <br/> При изменении количества повторов этой обработки я наблюдаю за временем выполнения. <br/> Меня озадачивает, почему время выполнения иногда отличается более чем в три раза, например, значения <i>time_min = 41200 time_max = 145000</i>. <br/> Компьютер имеет 6 ядер и 12 потоков, и в данный момент не нагружен другими задачами. Если я не ошибся в коде, но при этом наблюдается периодическое "захватывание" <i>ресурсов потоков</i> компьютера, как можно решить эту проблему, чтобы время выполнения колебалось в пределах 20%? <br/> _play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=537d0482efc78c4a05a2174015c2291c <br/>
  • 6 октября 2024 г. 11:04
Ответы на вопрос 4
Для оптимизации кода и уменьшения колебаний во времени выполнения есть несколько стратегий, которые вы можете рассмотреть. Хотя у меня нет доступа к вашему конкретному коду, могу дать общие рекомендации по оптимизации, которые могут помочь:

### 1. **Параллелизм и многопоточность**
- Используйте многопоточные библиотеки, такие как Rayon для Rust, чтобы распределить нагрузку по всем доступным ядрам. Это помогает эффективно использовать ресурсы процессора и сократить время обработки.
  
### 2. **Избегайте блокировок**
- Если в вашем коде есть блокировки (например, использование Mutex), старайтесь по возможности свести к минимуму время, на которое блокируется общий ресурс. Исследуйте возможность использования "lock-free" структур данных.

### 3. **Избегайте невыгодных аллокаций**
- Убедитесь, что ваше приложение не создает много временных объектов и не выполняет частые аллокации памяти. Используйте пул объектов или другие механизмы кэширования.

### 4. **Используйте профилирование**
- Используйте инструменты профилирования, такие как `cargo flamegraph`, чтобы выявить узкие места в вашем коде. Это даст вам четкое представление о том, какие части вашего приложения требуют оптимизации.

### 5. **Оптимизация алгоритмов**
- Проверьте алгоритмы, используемые в вашем коде. Иногда замена алгоритма на более эффективный может существенно уменьшить время выполнения. Например, это может быть уменьшение сложности с O(n^2) до O(n log n).

### 6. **Настройка параметров выполнения**
- В зависимости от того, как вы запускаете обработку, возможно, стоит поиграть с параметрами выполнения. Например, увеличить размер пула потоков или настроить параметры системы.

### 7. **Минимизируйте взаимодействие с ОС**
- Если ваша программа осуществляет много операций ввода-вывода, старайтесь минимизировать взаимодействие с файловой системой или сетью, так как эти операции могут существенно замедлять выполнение.

### 8. **Параметры компиляции**
- Убедитесь, что вы компилируете с оптимизацией. Используйте `cargo build --release` для создания оптимизированной версии вашего приложения.

### 9. **Тестирование на разных данных**
- Убедитесь, что данные, которые вы используете для тестирования, представляют собой заинтересованный набор. Случайные данные могут вести себя по-другому, чем заранее известные данные.

### 10. **Избегайте избыточности**
- Проверьте, нет ли избыточных операций в вашем цикле обработки. Оптимизация мелких деталей может привести к значительному времени выполнения.

Если вы предоставите конкретный код, я мог бы предложить более целенаправленные улучшения.
Не скажу ничего про алгоритм и корректность замеров, но время t01 и t02 ты точно измеряешь неправильно 

subsec_nanos
Returns the fractional part of this Duration, in nanoseconds.

This method does not return the length of the duration when represented by nanoseconds. The returned number always represents a fractional portion of a second (i.e., it is less than one billion).
https://doc.rust-lang.org/std/time/struct.Duration...

У структуры Duration есть операторы для сравнения, так что тебе не обязательно знать конкретное число, пока ты не выводишь его в консоль

let mut t01 = Duration::MIN;
let mut t02 = Duration::MAX;
if duration> t01 {
      t01 = duration; // здесь
   }
   if duration< t02 {
      t02 = duration; // и здесь
   }


UPD:


Комп 6 ядер 12 потоков ничем не нагружен. Если не накосячил с кодом, а так
захватывается периодически ресурс потоков компа, то как такое решить
и получать расхождение в пределах 20%?

1. Такой разброс, как у тебя показан - это норма. Нужно смотреть не на минимум/максимум, а на распределение (в комментах скинул график - там тоже минимум и максимум сильно различаются, но прогонов с таким временем мало)
2. Я не увидел в вопросе описания того, как происходит запуск. Хотябы в --release компилировал?
3. У тебя данные вполне статичные, так что компилятор при желании мог очень много наоптимизировать, что даст тебе некорректные результаты, но на распределение это влиять не должно.
Возможно OC выдала вторичный поток - частично лечится повышением приоритета процесса или выставлением определённого ядра, например через process lasso. 

Лучше создай массив вне цикла для хранения времени каждой итерации цикла и записывай туда, желательно не в куче [f32; N].

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

А сейчас ты записываешь лишь последний результат.

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

И учти коммент: mayton2019
Сейчас ты меряешь какой-то случайный процесс который в общей своей массе длиннее
чем твой изучаемый алгоритм.
2. Я не увидел в вопросе описания того, как происходит запуск. Хотябы в --release компилировал?

спасибо за помощь разобраться
да, > cargo run --release
в отличие от debug даёт общее ускорение выполнения, но между повторами сохраняется иногда двукратное расхождение времени выполнения, например для массива на 10к элементов и 30 повторов:
При значительном увеличении кол-ва элементов в массиве, например, до 10кк:
вот гуляет время от 45 ms до 89 ms на одинаковых условиях и наборе данных и думаю, что это не нормально ( случайные служебные процессы ), а косяк кода. Поэтому задал вопрос.
Похожие вопросы