2016-04-14 4 views
-1

Теоретически стоимость сложения/вычитания двойного слова принимается 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?

+1

** Мы ** знаем вопросы, начиная с «... мы знаем ...» начинаются с ложной предпосылки в большинстве случаев. Твой не исключение. – Olaf

+0

Вы должны рассмотреть возможность конвейерной обработки. Хорошим местом для чтения порядка синхронизации x86 являются таблицы инструкций Agner Fog. – EOF

ответ

2

В теории мы знаем, что сложение/вычитание двойного слова занимает 2 раза от одного слова.

Нет, мы не знаем.

Точно так же соотношение затрат однодискового умножения на добавление принимается за 3 из-за быстрого целочисленного множителя ЦП.

Нет, это не так.

Вы не измеряете инструкции. Вы измеряете заявления в своей программе. Который может или не может иметь отношения с инструкциями, которые ваш компилятор будет испускать. Мой компилятор, например, после исправления кода, чтобы он компилировал, векторизовал некоторые из циклов. Добавление нескольких значений для каждой инструкции. Первый цикл сам по-прежнему содержит 23 инструкции и по вашему коду все еще сообщается как 1 цикл.

Современные (как в последние 25 лет) Процессоры не выполняют одну инструкцию за раз. Они будут иметь сразу несколько инструкций в полете и могут вывести их из строя.

Затем у вас есть доступ к памяти. На вашем процессоре нет инструкций, которые могут принимать значение из памяти, добавить его в другое значение из памяти, а затем сохранить в третьей ячейке памяти. Таким образом, должно быть выполнено несколько инструкций. Кроме того, доступ к памяти стоит гораздо больше, чем арифметические инструкции, что все, что касается памяти (если оно не попадает в кеш-память L1 все время), будет зависеть от времени доступа к памяти.

Кроме того, RDTSC может даже не возвращать фактическое количество циклов. Некоторые процессоры имеют переменные тактовые частоты, но все же поддерживают TSC с одинаковой скоростью независимо от того, насколько быстро или медленнее работает ЦПУ, поскольку TSC используется операционной системой для сохранения времени. Другие нет.

Итак, вы не измеряете то, что, по вашему мнению, вы измеряете, и тот, кто сказал вам, что эти вещи либо слишком упрощали, либо не видели документацию по ЦП за два десятилетия.

+0

В литературе/теории отношение умножения к сложения принимается 3 в наихудшем случае. – user110219

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

  • Нет связанных вопросов^_^