2012-05-07 2 views
4

Использование:Как синхронизировать TSC по ядрам?

inline uint64_t rdtsc() 
{ 
    uint32_t cycles_high; 
    uint32_t cycles_low; 

    asm volatile ("CPUID\n\t" 
     "RDTSC\n\t" 
     "mov %%edx, %0\n\t" 
     "mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low):: 
     "%rax", "%rbx", "%rcx", "%rdx"); 
    return (((uint64_t)cycles_high << 32) | cycles_low); 
} 

нить 1 погонный

while(globalIndex < COUNT) 
{ 
    while(globalIndex %2 == 0 && globalIndex < COUNT) 
    ; 
    cycles[globalIndex][0] = rdtsc(); 
    cycles[globalIndex][1] = cpuToBindTo; 
    __sync_add_and_fetch(&globalIndex,1); 
} 

нить 2 работает

while(globalIndex < COUNT) 
{ 
    while(globalIndex %2 == 1 && globalIndex < COUNT) 
    ; 
    cycles[globalIndex][0] = rdtsc(); 
    cycles[globalIndex][1] = cpuToBindTo; 
    __sync_add_and_fetch(&globalIndex,1); 
} 

я вижу

CPU  rdtsc()   t1-t0 
11 = 5023231563212740 990 
03 = 5023231563213730 310 
11 = 5023231563214040 990 
03 = 5023231563215030 310 
11 = 5023231563215340 990 
03 = 5023231563216330 310 
11 = 5023231563216640 990 
03 = 5023231563217630 310 
11 = 5023231563217940 990 
03 = 5023231563218930 310 
11 = 5023231563219240 990 
03 = 5023231563220230 310 
11 = 5023231563220540 990 
03 = 5023231563221530 310 
11 = 5023231563221840 990 
03 = 5023231563222830 310 
11 = 5023231563223140 990 
03 = 5023231563224130 310 
11 = 5023231563224440 990 
03 = 5023231563225430 310 
11 = 5023231563225740 990 
03 = 5023231561739842 310 
11 = 5023231561740152 990 
03 = 5023231561741142 310 
11 = 5023231561741452 12458 
03 = 5023231561753910 458 
11 = 5023231561754368 1154 
03 = 5023231561755522 318 
11 = 5023231561755840 982 
03 = 5023231561756822 310 
11 = 5023231561757132 990 
03 = 5023231561758122 310 
11 = 5023231561758432 990 
03 = 5023231561759422 310 

Я не знаю, как я получил понг 12458, но было интересно, почему я видел 310-990-310 вместо 650-650-650. Я думал, что tsc должен быть синхронизирован по всем ядрам. мой флаг constant_tsc cpu включен.

ответ

0

У вас есть архитектура памяти NUMA? Глобальный счетчик может быть размещен в ОЗУ, который находится на пару шагов для одного из процессоров и локального для другого. Вы можете проверить это, установив свои потоки на ядра на том же узле NUMA.

EDIT: Я догадывался об этом, так как производительность была специфичной для процессора.

EDIT: Что касается синхронизации TSC. Я не знаю про легкий путь, который не означает, что его нет! Что произойдет, если вы возьмете ядро ​​1 в качестве эталонного такта и затем сравните его с ядром 2? Если вы делали это сравнение много раз и принимали минимум, у вас могло бы быть хорошее приближение. Это должно обрабатывать случай, когда вы выгружаетесь в середине сравнения.

+0

Я запускаю это на сервере с 2 гнездами, используя cpus 3 и 11, которые находятся на сокете 2. lscpu | grep NUMA возвращает ' NUMA node0 CPU (s): 0,2,4,6,8,10 NUMA node1 CPU (s): 1,3,5,7,9,11 ' – fission

+0

Только для ада из этого ... что происходит, когда вы запускаете потоки на разных ЦП, отличных от 3 и 11? – johnnycrash

+0

Является ли globalindex неустойчивым? Хотя, для глобалов, летучесть, вероятно, не требуется. Вы компилируете с -O3? Кроме того, чтобы получить более чистую статистику, мы можем суммировать статистику в массивах, которые не загрязняют строки кэша для другого потока. Используйте struct для хранения процессора/времени, а затем добавьте пару фиктивных полей, чтобы он добавлял до 64 байтов. Затем объявите циклы с __attribute ((align (64)).После этого каждое обновление должно быть в чистой чистой строке кэша. – johnnycrash

1

Что вы используете для этого кода? Синхронизация TSC должна выполняться в ОС/ядре и зависит от оборудования. Например, вы можете передать флаг, как powernow-k8.tscsync=1, в параметры загрузки ядра через ваш загрузчик.

Вам необходимо найти правильный метод синхронизации TSC для вашей комбинации ОС и оборудования. По большому счету, все это автоматизировано - я не удивлюсь, если вы работаете на настраиваемом ядре или без оборудования i686?

Если вы ищете в Google правильные условия, вы найдете много ресурсов, таких как обсуждение рассылки по этой теме. Например, вот one algorithm being discussed (хотя, видимо, это не очень хорошо). Тем не менее, это не то, о чем нужно беспокоиться разработчикам пользовательских прав - это тайное колдовство, с которым только разработчики ядра должны беспокоиться о своих головах.

В принципе, это задача ОС во время загрузки, чтобы синхронизировать счетчики TSC между всеми процессорами и/или ядрами на машине SMP с определенным пределом погрешности. Если вы видите цифры, которые неактивны, что-то не так с синхронизацией TSC, и ваше время было бы лучше потрачено на то, чтобы выяснить, почему ваша ОС не синхронизировала TSC правильно, а не пыталась реализовать собственный алгоритм синхронизации TSC.

Смежные вопросы