Теоретически стоимость сложения/вычитания двойного слова принимается 2 раза за одно слово. Точно так же соотношение затрат однодискового умножения к добавлению принимается как 3. Я написал следующую программу на C с использованием GCC на Ubuntu LTS 14.04, чтобы проверить количество тактов на моей машине, Intel Sandy Bridge Corei5-2410M. Хотя, большую часть времени программа возвращает 6 тактов для 128-битного добавления, но я взял наилучший вариант. Я скомпилировал с помощью команды (ССАГПЗ -o вл -O3 cost.c) и результат приведен нижеИспользование rdtsc() в моей программе для получения количества тактовых циклов для одно- и двухсловных операций?
32-bit Add: Clock cycles = 1 64-bit Add: Clock cycles = 1 64-bit Mult: Clock cycles = 2 128-bit Add: Clock cycles = 5
Программа выглядит следующим образом:
#define n 500
#define counter 50000
typedef uint64_t utype64;
typedef int64_t type64;
typedef __int128 type128;
__inline__ utype64 rdtsc() {
uint32_t lo, hi;
__asm__ __volatile__ ("xorl %%eax,%%eax \n cpuid"::: "%rax", "%rbx", "%rcx", "%rdx");
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return (utype64)hi << 32 | lo;
}
int main(){
utype64 start, end;
type64 a[n], b[n], c[n];
type128 d[n], e[n], f[n];
int g[n], h[n];
unsigned short i, j;
srand(time(NULL));
for(i=0;i<n;i++){ g[i]=rand(); h[i]=rand(); b[i]=(rand()+2294967295); e[i]=(type128)(rand()+2294967295)*(rand()+2294967295);}
for(j=0;j<counter;j++){
start=rdtsc();
for(i=0;i<n;i++){ a[i]=(type64)g[i]+h[i]; }
end=rdtsc();
if((j+1)%5000 == 0)
printf("%lu-bit Add: Clock cycles = %lu \t", sizeof(g[0])*8, (end-start)/n);
start=rdtsc();
for(i=0;i<n;i++){ c[i]=a[i]+b[i]; }
end=rdtsc();
if((j+1)%5000 == 0)
printf("%lu-bit Add: Clock cycles = %lu \t", sizeof(a[0])*8, (end-start)/n);
start=rdtsc();
for(i=0;i<n;i++){ d[i]=(type128)c[i]*b[i]; }
end=rdtsc();
if((j+1)%5000 == 0)
printf("%lu-bit Mult: Clock cycles = %lu \t", sizeof(c[0])*8, (end-start)/n);
start=rdtsc();
for(i=0;i<n;i++){ f[i]=d[i]+e[i]; }
end=rdtsc();
if((j+1)%5000 == 0){
printf("%lu-bit Add: Clock cycles = %lu \n", sizeof(d[0])*8, (end-start)/n);
printf("f[%hu]= %ld %ld \n\n", i-7, (type64)(f[i-7]>>64), (type64)(f[i-7]));}
}
return 0;
}
Есть две вещи, в результате чего Меня беспокоит.
1) Может ли число тактов для (64-разрядного) умножения стать 2?
2) Почему количество тактовых циклов для сложения двойного слова более чем в 2 раза больше, чем одно слово?
В основном я беспокоюсь о случае (2). Теперь возникает вопрос, что это из-за моей программной логики? Или это связано с оптимизацией компилятора GCC?
** Мы ** знаем вопросы, начиная с «... мы знаем ...» начинаются с ложной предпосылки в большинстве случаев. Твой не исключение. – Olaf
Вы должны рассмотреть возможность конвейерной обработки. Хорошим местом для чтения порядка синхронизации x86 являются таблицы инструкций Agner Fog. – EOF