Зачем изучать Тайники?

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

  • Доступ к элементам по строкам
function rowAccess(A::AbstractMatrix)
      for i in 1:size(A)[1]
          for j in 1:size(A)[2]
              A[i,j] = A[i,j]+1
          end
      end
      return A
end
  • Доступ к элементам по столбцам
function colAccess(A::AbstractMatrix)
      for i in 1:size(A)[1]
          for j in 1:size(A)[2]
              A[j,i] = A[j,i]+1
          end
      end
      return A
end

Я буду использовать язык программирования Julia, но вы можете использовать любой другой язык программирования.

Когда я запускаю оба из них независимо (поставляя 5000 на 5000) матрицу A) и тестирую ее, я наблюдаю, что функция rowAccess выполняется 160,2 мс, а colAccess завершается через 16,4 мс!!

@btime _ = colAccess(A);
16.400 ms (0 allocations: 0 bytes)
@btime _ = rowAccess(A);
160.207 ms (0 allocations: 0 bytes)

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

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

Для полного сообщения в блоге перейдите по следующей ссылке: https://tgautam03.github.io/2021/10/31/CacheBasics/

Первоначально опубликовано на https://tgautam03.github.io 31 октября 2021 г.