у меня на ОДНОЙ машине i7 с 6 ядрами
1)FreeBSD 7.1
2)WinXP
одинак.asm-код WinXP исполняет быстрее, чем FreeBSD!!!!!!!!!!Linux выполняет тот же код, и не важно — inline asm или просто С-код за столько же, за сколько WinXP, и быстрее, чем FreeBSD на 25% !!!!!!!!!!!!
кто может объяснить? может FreeBSD постоянно прерывает процесс, переключая контексты? зачем? у меня i7 c 6(!!!) ядрами!!! на ядре с тестом ничего больше не работает.
Может какие-н. ключи компиляции ядра FreeBSD (не)надо вкючать?
я написал тест на С и скомпилял его на MSVC. посмотрел его дисасм и реализовал его один к одному в gcc (inline asm).
В WinXP тест реботает 15 сек, а в FreeBSD 20 сек!!!!!!!!!!!
вот исходники:
#if defined(_MSC_VER) || defined(_WIN32) || defined(WIN32)
#include <Windows.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <ctype.h>
#include <locale.h>
#include <signal.h>
#include <time.h>
#if defined(__CYGWIN__) // !defined(_MSC_VER)
#include <basetyps.h>
#elif !defined(_MSC_VER)
#include <stdint.h>
#endif
typedef unsigned long u32;
#ifdef _MSC_VER
typedef unsigned __int64 u64;
#else
typedef uint64_t u64;
#endif
u64 overclock()
{
#ifndef _MSC_VER
clock_t t2, t1 = clock();
do {
t2 = clock();
} while (t1 == t2);
return t2;
#else
#if 0
return GetTickCount();
#else
FILETIME t1,t2;
GetSystemTimeAsFileTime(&t1);
do {
GetSystemTimeAsFileTime(&t2);
} while (t1.dwLowDateTime == t2.dwLowDateTime);
return (((u64)(t2.dwHighDateTime)) <;<; 32) + t2.dwLowDateTime;
#endif
#endif
}
u64 myclock()
{
#ifndef _MSC_VER
return clock();
#else
#if 0
return GetTickCount();
#else
FILETIME t;
GetSystemTimeAsFileTime(&t);
return (((u64)(t.dwHighDateTime)) <;<; 32) + t.dwLowDateTime;
#endif
#endif
}
void print_dtime(const char* s, u64* t1, u64* t2)
{
#ifdef _MSC_VER
double dt = ((double)(__int64)(*t2-*t1)) / 10000.0;
fprintf(stderr, "%s%I64u = %f ms\n", s, (*t2-*t1), dt);
#else
double dt = ((double)(*(clock_t*)(t2) - *(clock_t*)(t1))) ;/// 10000.0;
fprintf(stderr, "%s%f ms \n", s, dt*10);
#endif
fflush(stderr);
}
int test()
{
#define _MAX_CNT ((1<<17 )-1)
static unsigned int buf[0x10000];
u32 i=0,j=0;
u64 t1,t2;
printf("start\n");
t1 = overclock();
#ifdef __FREEBSD__
//gccalign8;
__asm__ __volatile__(
"nop;nop; \n" /* для выравнивания на 16 байт, как в MSVC. подбирал вручную */
"xorl %Мi,%Мi \n\t"
"jmp 30f \n"
"nop;nop;nop;nop; \n" /* для выравнивания на 16 байт. */
"nop;nop;nop;nop; \n"
"nop;nop;nop;nop; \n"
"\n30:\n\t" /*L_start*/
"xorl %%esi,%%esi \n\t"
"jmp 1f \n"
"1: \n\t"
"leal (%%esi,%Мi), %Лx \n\t"
"andl $0x0F, %Лx \n\t"
"movl %%esi, (%Мx,%Лx,4) \n\t"
"addl $1, %%esi \n\t"
"cmpl $0x1FFFF, %%esi \n\t"
"jb 1b \n\t "
"add $1, %Мi \n\t"
"cmpl $0x1FFFF, %Мi \n\t"
"jb 30b \n\t "
:
: "d"(buf)
:"esi","edi"
);
#else
for (i=0; i<;_MAX_CNT; ++i)
{
for (j=0; j<;_MAX_CNT; ++j)
{
buf[(i+j)&(0x10-1)] = j;//просто так,чтоб не MSVC заоптимизировал, но в то же время чтоб индексы i и j были в регистрах
}
}
/*
это дисасм MSVC
00401055 xor edi,edi
00401057 jmp test+60h (401060h)
00401059 lea esp,[esp]
94: {
95: for (j=0; j<;_MAX_CNT; ++j)
00401060 xor esi,esi ;;;выравнено на 16 байт
00401062 jmp test+70h (401070h)
... ;хлам-заполнитель для выравнивания на 16 байт
96: {
97: buf[(i+j)&(0x10000-1)] = j;
00401070 lea ecx,[esi+edi] ;;;выравнено на 16 байт
00401073 and ecx,0Fh
00401079 mov dword ptr _buf (4033A0h)[ecx*4],esi
00401080 add esi,1
00401083 cmp esi,1FFFFh
00401089 jb test+70h (401070h)
0040108B add edi,1
0040108E cmp edi,1FFFFh
00401094 jb test+60h (401060h)
*/
#endif
t2 = myclock();
print_dtime("finish ", &t1, &t2);
printf("finish i,j (%u,%u)\n",i,j);
return 0;
}
int main(int argc, char* argv[])
{
test();
return 0;
}
на FreeBSD должно быть даже быстрее, потому что указатель на buf находится в регистре, а в MSVC идет обращение к памяти.
ничего не понимаю. подскажите, в чем дело.
какие ключи компиляции ядра FreeBSD (не)надо вкючать?