Я реализую математическую библиотеку в C, которая интенсивно использует умножения.Первоначально все мои умножения были сделаны с использованием uint16_t
.Недавно я изменил многие из них на uint32_t
и увидел, что время выполнения моего кода стало почти вдвое больше.Я был сбит с толку, так как думал, что в процессорах Intel x64 32- и 16-разрядные умножения занимают одинаковые такты.Я написал диагностический код, пожалуйста, найдите его ниже
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include "cpucycles.c"
#define REPEAT 10000
#define OUT_REPEAT 100000
void main(){
uint16_t a_16[REPEAT], b_16[REPEAT], c_16[REPEAT];
uint32_t a_32[REPEAT], b_32[REPEAT], c_32[REPEAT];
int32_t i,j;
uint64_t clock1, clock2, CLOCK16, CLOCK32;
uint64_t acc=0;
time_t t;
srand((unsigned) time(&t));
clock1=clock2=CLOCK16=CLOCK32=0;
for(j=0;j<OUT_REPEAT;j++){
for(i=0;i<REPEAT;i++){
a_16[i]=rand()& ( (1<<13) -1); //need 13-bit integers only
b_16[i]=rand()& ( (1<<13) -1);
a_32[i]=rand()&( (1<<19) -1);
b_32[i]=rand()&( (1<<19) -1); //need 19-bit integers only
}
clock1=cpucycles();
for(i=0;i<REPEAT;i++){
c_16[i]=a_16[i]*b_16[i];
}
clock2=cpucycles();
CLOCK16=CLOCK16+(clock2-clock1);
clock1=cpucycles();
for(i=0;i<REPEAT;i++){
c_32[i]=a_32[i]*b_32[i];
}
clock2=cpucycles();
CLOCK32=CLOCK32+(clock2-clock1);
for(i=0;i<REPEAT;i++){
acc=(acc+(c_32[i]-(uint32_t)c_16[i])); //this is just to prevent compiler optimization
}
printf("Iteration: %d, acc:%llu\n", j, acc);
acc=0;
}
printf("\n--------------------------------------------\n");
printf("Time for 16 bit multiplication : %llu\n", CLOCK16/OUT_REPEAT);
printf("Time for 32 bit multiplication : %llu\n", CLOCK32/OUT_REPEAT);
printf("\n--------------------------------------------\n");
}
Код процессора от ECRYPT и приведенный ниже
#include "cpucycles.h"
long long cpucycles(void)
{
unsigned long long result;
asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax"
: "=a" (result) :: "%rdx");
return result;
}
Результат от одного пробного прогона,использование одного ядра и гиперпоточности / отключено TurboBoost
--------------------------------------------
Time for 16 bit multiplication : 2795
Time for 32 bit multiplication : 4190
--------------------------------------------
и, наконец, мой cpuinfo (отрывок), заданный lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Model name: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
Теперь мой вопрос:
Правильно ли, что на платформах x64 16-битное умножение занимает почти половину общего времени, чем 32-битное умножение?Или я делаю что-то не так.
Если да, не могли бы вы показать мне некоторые ссылки, чтобы оправдать такое поведение?
Заранее спасибо,Я ценю вашу помощь.