Как я намеренно читаю из основной памяти против кеша? - PullRequest
5 голосов
/ 08 февраля 2009

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


Edit:

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

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"? или я здесь совсем не в базе?

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

1 Ответ

7 голосов
/ 08 февраля 2009

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

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

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


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

  • Вещи, которые вы делаете с 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 - это некоторое приращение, равное примерно одной пятой длины фрагмента.

...