Необходимо написать небольшой тест для непосредственного определения размера и ассоциативности TLB (точнее, L1 D-TLB). Если кто знает, как это сделать - помогите, плз! Кстати, вроде на некоторых проц. есть L2 D-TLB, для него можно какие-либо параметры определить?
URL http://www.agner.org/optimize/asmlib.zip там пример теста с исходниками, подробно не разбирал, но может подойдёт
Y_Mur, спасибо, как получить эти цифры при помощи этой программы разобрался. Остался вопрос: как продемонтрировать, что TLB действительно такого размера (в программе, точнее, в процедуре INTERPRET_TLB, насколько я понял, просто идет получение информации, грубо говоря, "зашитой в процессоре"). Т.е. надо построить какой-либо тест, который, например, на некотором наборе размера меньшего размера TLB работал бы быстрее, а с увеличением набора скорость разко падала (например, как это сделано в тесте RightMark Memory Analyzer). Или показать, что некоторый код без оптимизации под TLB работает плохо, а с оптимизацией - хорошо.
ilvip Просто замеряешь по rdtsc время чтения N двордов, каждый со смещением на 4К+64 от предыдущего (64 - размер линейки кэша). При N = числу записей TLB будет скачок (для наглядности лучше пересчитать время в скорость R=t*k/N, k - масштабный коэфф.)
Боюсь, что с подобным тестом ничего не выйдет. Программно нельзя отключить/включить TLB. Единственное, что можно делать - это постоянно сбрасывать кэш TLB перезаписью Cr3 или инструкцией invlpg. Но для этого придется загружать драйвер, который в цикле будет постоянно сбрасывать кэш. Но это явно не совсем честное решение. ЗЫ: Любая информация о возможностях процессора, в т.ч. и кэшах, может быть получена с помощью cpuid. См. Intel Manual
leo, самое обидное, что я в общих чертах так и делал. При этом - из-за кривизны рук, похоже - результата никакого (т.е. число тактов на одно чтение стабильно держится в районе 3 при включенном кэшировании и в районе ~60 без кэширования, вне зависимости от числа чтений). Если у кого есть возможность - посмотрите программу, может найдете стратегические просчеты... Идея такая: создали массив указателей на void (как раз 32 бита размер каждого), нулевой элемент ссылается на (4К+64)ый, ... и так далее, (i*(4K+64))ый - на нулевой, где i изменяем от 2 до 512 в цикле. В этом же цикле вызываем такую функцию (count передаем 1000*i, в src - указатель на нулевой элемент): Код (Text): void __declspec(naked) __cdecl ReadTLB(void* src, __int32 count) { __asm { mov eax, [esp+4] // поместить src в eax mov ecx, [esp+8] // поместить count в ecx ALIGN 16 $loop: mov eax, [eax] // Записать в eax то, что лежит по адресу в eax mov eax, [eax] // Ещё раз sub ecx, 2 jnz $loop ret } } Время при помощи rdtsc засекаем для всего выполнения процедуры. Так вот, все эти манипуляции к результату не приводят, увы. Интересно, где накосячил?
ilvip Перемудрил с указателями, вот и накосячил m1[k*stride] = &m1[k*(stride+1)] пишет в m1[0] указатель на самого себя и в результате ReadTlb всегда читает один и тот же dword m1[0]. Видимо нужно &m1[(k+1)*stride]. И кстати не понятно почему stride=4K+65, а не 64 - какой в этом смысл ? Если речь идет только о тесте TLB (а не вообще скорости чтения), то PAGE_NOCACHE и сброс TLB (да еще в ринг 0 ради записи в cr3) - тут совершенно ни к чему, т.к. это лишь добавляет лишние задержки, которые скрывают и зашумляют точку излома К тому же сама методика с накручиванием по 1000 проходов, да еще для всех (i=512; i>2; i-=2) и без REALTIME_PRIORYTY чревата случайными выбросами за счет виндовых "происков" с переключением потоков. В данном случае ИМХО "лучше меньше, да лучше"
leo, спасибо. 65 - это описка, как и нулевой шаг. Другое дело, что на моем раритетном PentiumII-300 этот код ни после каких манипуляций так и не заработал. В итоге догадался, переписал под Линух и запустил на P3 - нормально отработало. Так что проблема исчерпана, ещё раз спасибо за помощь.