Как я намеренно читаю из основной памяти по сравнению с кешем?

Итак, меня учат ассемблеру, и у нас есть задание: найти разницу во времени между чтением из памяти и чтением из кеша. Мы должны сделать это, создав 2 цикла и синхронизировав их. (один читает из основной памяти, а другой из кеша). Дело в том, что я не знаю и не могу найти ничего, что подсказывало бы мне, как читать из кеша или основной памяти =/. Не могли бы вы мне помочь? Я делаю это в MASM32. Я понимаю, как делать циклы, и хорошо понимаю язык ассемблера, но я просто не могу заставить его читать =/


Изменить:

У меня есть вопрос, я сделал это ...

mov ecx, 100 ;loop 100 times
xor eax, eax ;set eax to 0
_label:
mov eax, eax ;according to me this is read memory is that good?
dec ecx ;dec loop
jnz _label ;if still not equal to 0 goes again to _label

... это будет нормально?


Редактировать 2:

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

Кроме того, можно ли читать из разных регистров во втором цикле (тот, который не читает из кеша), если я даю различные инструкции «mov»? или я тут совсем не в теме?

Извините за все эти вопросы, но еще раз спасибо за вашу помощь.


person Tsundoku    schedule 08.02.2009    source источник


Ответы (1)


Читать из кеша. есть цикл, который считывается с одного и того же (или очень похожего) адреса памяти:

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

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


Чтобы ответить на ваш второй вопрос:

  • То, что вы делаете с ecx и jnz, выглядит нормально (я не знаю, насколько точен/чувствителен ваш таймер, но вы можете зациклиться более 100 раз)

  • mov eax, eax не является "прочитанной памятью"... это неоперативная операция, которая перемещает eax в eax. Вместо этого я думаю, что синтаксис MASM для чтения из памяти больше похож на mov eax,[esi] («прочитать из ячейки памяти, адрес которой содержится в esi»)

  • В зависимости от того, какую операционную систему вы используете, вы должны читать из адреса памяти, который действительно существует и доступен для чтения. В Windows, например, приложению не разрешается выполнять mov esi, 0, за которым следует mov eax, [esi], потому что приложению не разрешено читать память, адрес/местоположение которой равно нулю.


Чтобы ответить на ваш третий вопрос:

timeGetTime, GetTickCount и счетчик производительности

Ваше упоминание timeGetTime, GetTickCount и Performance Counter подразумевает, что вы работаете под Windows.

Да, они возвращают текущее время с разным разрешением/точностью: например, GetTickCount имеет разрешение около 50 мс, поэтому он не может синхронизировать события, которые длятся менее 50 мс, неточно, когда синхронизируют события, которые длятся всего 50-100 мс. мс Вот почему я сказал, что 100 в вашем ecx, вероятно, недостаточно велико.

Функция QueryPerformanceCounter, вероятно, самый точный таймер, который у вас есть.

Чтобы использовать любой из этих таймеров в качестве интервального таймера:

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

ничего, если я даю различные инструкции "mov"?

Да, я так думаю. Я думаю, вы можете сделать это так (остерегайтесь, я не уверен/не помню, является ли это правильным синтаксисом MASM для чтения из памяти имени)...

mov eax,[memory1]
mov eax,[memory2]
mov eax,[memory3]
mov eax,[memory4]
mov eax,[memory5]

... где с memory1 по memory5 — это адреса широко разнесенных глобальных переменных в вашем сегменте данных.

Или вы могли бы сделать...

mov eax,[esi]
add esi,edx
mov eax,[esi]
add esi,edx
mov eax,[esi]
add esi,edx
mov eax,[esi]
add esi,edx
mov eax,[esi]

... где esi указывает на конец длинного фрагмента памяти, а edx - некоторый приращение, равное примерно одной пятой длины фрагмента.

person ChrisW    schedule 08.02.2009