Дещо довший відповідь, який пояснює, чому більш ефективно лівий індекс змінюється найшвидше. Є дві ключові речі, які вам потрібно зрозуміти.
По-перше, MATLAB (і Fortran, але не C та більшість інших мов програмування) зберігає масиви в пам'яті в "стовпчику основного порядку". наприклад, якщо A - матриця 2 на 3 на 10, то записи зберігатимуться в пам'яті в порядку
A (1,1,1)
A (2,1,1)
A (1,2,1)
A (2,2,1)
A (1,3,1)
A (2,3,1)
A (1,1,2)
A (2,1,2)
...
A (2,3,10)
Цей вибір основного порядку стовпців є довільним - ми можемо просто прийняти конвенцію про "основний рядок рядків", і насправді це робиться в C та деяких інших мовах програмування.
Друга важлива річ, яку вам потрібно зрозуміти, - це те, що сучасні процесори не мають доступу до пам’яті одночасно, а швидше завантажують і зберігають «кеш-лінії» з 64 або навіть 128 суміжних байтів (8 або 16 подвійних точних чисел з плаваючою комою) за один раз із пам’яті. Ці шматки даних тимчасово зберігаються в швидкому кеш-пам'яті та записуються назад за потребою. (На практиці архітектура кеша зараз досить складна з цілим 3 або 4 рівнями кеш-пам’яті, але основну думку можна пояснити однорівневим кешем такого типу, який мали комп'ютери в мої молодші дні.)
A
Якщо петлі вкладені таким чином, щоб внутрішній цикл оновлював індексний рядок, тоді записи до масиву будуть доступні в порядку A (1,1), A (2,1), A (3,1), ... Коли Перший запис A (1,1) доступний, система внесе кеш-рядок, що містить A (1,1), A (2,1), ..., A (8,1) в кеш з головної пам'яті . Наступні 8 ітерацій внутрішнього циклу працюють на цих даних без додаткових передач основної пам'яті.
Якщо в альтернативному варіанті, ми структуруємо петлі так, щоб індекс стовпця змінювався у самій внутрішній петлі, то до записів A можна отримати доступ у порядку A (1,1), A (1,2), A (1,3 ), ... У цьому випадку перший доступ принесе A (1,1), A (2,1), ..., A (8,1) в кеш з головної пам'яті, але 7/8 ці записи не використовуються. Тоді доступ до A (1,2) у другій ітерації приведе ще 8 записів із основної пам'яті тощо. До того моменту, коли код зайнявся роботою над другою лінією матриці, запис A (2,1) цілком може бути видалений з кешу, щоб отримати доступ до інших необхідних даних. В результаті код генерує в 8 разів більше трафіку, ніж необхідно.
Деякі оптимізуючі компілятори здатні автоматично реструктурувати петлі, щоб уникнути цієї проблеми.
Багато алгоритми чисельних лінійних алгебр для множення матриць і множника можуть бути оптимізовані для ефективної роботи зі схемою упорядкування рядка-магістраль або стовпчик-основний залежно від мови програмування. Це неправильний спосіб може мати істотний негативний вплив на продуктивність.
For
петлі дуже повільні в MATLAB. Ви повинні уникати явних циклів у MATLAB, коли це можливо. Замість цього, як правило, проблема може виражатися в матричних / векторних операціях. Це MATLABic шлях. Існує також багато вбудованих функцій для ініціалізації матриць тощо. Наприклад, є функція one () , яка встановить всі елементи матриці на 1 (шляхом розширення, на будь-яке значення шляхом множення (скаляр) помножене на матрицю all-one)). Він також працює на 3-D масивах (на мою думку, тут висвітлено приклад).