Как справедливо было
замеченоАвтор: watch-maker
Дата: 10.02.12
— оптимизатор г++ слишком хорош для данного случая, а я писал на работе, слишком хотел домой и не подумал об этом. Посыпаю голову пеплом, и все такое.
В общем я нагрузил алгоритм еще одной функцией, которая принимает в себя число-счетчик цикла и на его основе считает всякую фигню. Ну типа полезную работу делает.
Также я на отдельно замеряю среднее количество тиков работы этой функции и вычитаю это потом из результата.
Кратко — результаты без оптимизации и с -O2 практически выровнялись. Разница приблизительно в 1,3 раза, switch выигрывает.
Но вот, сюрприз, с -O3 switch внезапно начинает обходить if на два порядка.
Код:
#include <iostream>
#include <stdlib.h>
using namespace std;
#include <stdint.h>
#include <math.h>
#define TESTS_COUNT 100
#define SOME somework(num)
#define ELSIF(_x) else if (num == _x) { SOME; }
#define SCASE(_x) case _x: { SOME; } break;
#define CYCLE(_type, _count) for (_type i = 0; i < _count; i++)
#define LONG_CYCLE CYCLE(unsigned long long, TESTS_COUNT*TESTS_COUNT*TESTS_COUNT)
#define TESTS_COUNT_CYCLE CYCLE(int, TESTS_COUNT)
unsigned long long somewariable = 0;
static inline unsigned long long tick()
{
unsigned long long d;
__asm__ __volatile__ ("rdtsc" : "=A" (d) );
return d;
}
void somework(int num)
{
int a = sin(num);
somewariable = cos(a+++num);
}
unsigned long long someworkTicks()
{
unsigned long long ticks_start, ticks_end;
ticks_start = tick();
TESTS_COUNT_CYCLE { somework(i); }
ticks_end = tick();
return (ticks_end - ticks_start)/TESTS_COUNT;
}
void test_if(int num)
{
if (num == 0) { SOME; }
ELSIF(1) ELSIF(2) ELSIF(3) ELSIF(4) ELSIF(5) ELSIF(6) ELSIF(7) ELSIF(8) ELSIF(9) ELSIF(10)
ELSIF(11) ELSIF(12) ELSIF(13) ELSIF(14) ELSIF(15) ELSIF(16) ELSIF(17) ELSIF(18) ELSIF(19) ELSIF(20)
ELSIF(21) ELSIF(22) ELSIF(23) ELSIF(24) ELSIF(25) ELSIF(26) ELSIF(27) ELSIF(28) ELSIF(29) ELSIF(30)
ELSIF(31) ELSIF(32) ELSIF(33) ELSIF(34) ELSIF(35) ELSIF(36) ELSIF(37) ELSIF(38) ELSIF(39) ELSIF(40)
ELSIF(41) ELSIF(42) ELSIF(43) ELSIF(44) ELSIF(45) ELSIF(46) ELSIF(47) ELSIF(48) ELSIF(49) ELSIF(50)
ELSIF(51) ELSIF(52) ELSIF(53) ELSIF(54) ELSIF(55) ELSIF(56) ELSIF(57) ELSIF(58) ELSIF(59) ELSIF(60)
ELSIF(61) ELSIF(62) ELSIF(63) ELSIF(64) ELSIF(65) ELSIF(66) ELSIF(67) ELSIF(68) ELSIF(69) ELSIF(70)
ELSIF(71) ELSIF(72) ELSIF(73) ELSIF(74) ELSIF(75) ELSIF(76) ELSIF(77) ELSIF(78) ELSIF(79) ELSIF(80)
ELSIF(81) ELSIF(82) ELSIF(83) ELSIF(84) ELSIF(85) ELSIF(86) ELSIF(87) ELSIF(88) ELSIF(89) ELSIF(90)
ELSIF(91) ELSIF(92) ELSIF(93) ELSIF(94) ELSIF(95) ELSIF(96) ELSIF(97) ELSIF(98) ELSIF(99)
}
void test_switch(int num)
{
switch (num)
{
SCASE(0)
SCASE(1) SCASE(2) SCASE(3) SCASE(4) SCASE(5) SCASE(6) SCASE(7) SCASE(8) SCASE(9) SCASE(10)
SCASE(11) SCASE(12) SCASE(13) SCASE(14) SCASE(15) SCASE(16) SCASE(17) SCASE(18) SCASE(19) SCASE(20)
SCASE(21) SCASE(22) SCASE(23) SCASE(24) SCASE(25) SCASE(26) SCASE(27) SCASE(28) SCASE(29) SCASE(30)
SCASE(31) SCASE(32) SCASE(33) SCASE(34) SCASE(35) SCASE(36) SCASE(37) SCASE(38) SCASE(39) SCASE(40)
SCASE(41) SCASE(42) SCASE(43) SCASE(44) SCASE(45) SCASE(46) SCASE(47) SCASE(48) SCASE(49) SCASE(50)
SCASE(51) SCASE(52) SCASE(53) SCASE(54) SCASE(55) SCASE(56) SCASE(57) SCASE(58) SCASE(59) SCASE(60)
SCASE(61) SCASE(62) SCASE(63) SCASE(64) SCASE(65) SCASE(66) SCASE(67) SCASE(68) SCASE(69) SCASE(70)
SCASE(71) SCASE(72) SCASE(73) SCASE(74) SCASE(75) SCASE(76) SCASE(77) SCASE(78) SCASE(79) SCASE(80)
SCASE(81) SCASE(82) SCASE(83) SCASE(84) SCASE(85) SCASE(86) SCASE(87) SCASE(88) SCASE(89) SCASE(90)
SCASE(91) SCASE(92) SCASE(93) SCASE(94) SCASE(95) SCASE(96) SCASE(97) SCASE(98) SCASE(99)
}
}
struct STicksData
{
unsigned long long ticks_start, ticks_if, ticks_case;
};
STicksData test(int num, unsigned long long st)
{
STicksData data;
data.ticks_start = tick();
TESTS_COUNT_CYCLE { test_if (num); }
data.ticks_if = tick();
TESTS_COUNT_CYCLE { test_switch(num); }
data.ticks_case = tick();
cout << "Number: " << num << "; ";
cout << "if: " << data.ticks_if - data.ticks_start - st << "; ";
cout << "case: " << data.ticks_case - data.ticks_if - st << "; ";
// cout << "Total: " << (data.ticks_case - data.ticks_start) << endl;
cout << endl;
return data;
}
// -----------------------------------------------------------------------------------------------------------------------------
int main ()
{
unsigned long long st = someworkTicks();
STicksData allTicks[TESTS_COUNT];
TESTS_COUNT_CYCLE
{
allTicks[i] = test(i, st);
}
unsigned long long average_if = 0, average_switch = 0, average_total = 0;
TESTS_COUNT_CYCLE
{
average_if += (allTicks[i].ticks_if - allTicks[i].ticks_start);
average_switch += (allTicks[i].ticks_case - allTicks[i].ticks_if );
// average_total += (allTicks[i].ticks_case - allTicks[i].ticks_start);
}
cout << "Average ticks" << endl;
cout << "if: " << (average_if /TESTS_COUNT) << endl;
cout << "case: " << (average_switch/TESTS_COUNT) << endl;
// cout << "Total: " << (average_total /TESTS_COUNT) << endl;
return 0;
}
Результат без оптимизаций
sheridan@amd-gentoo tests % g++ if-case.cpp -o si; ./si
Number: 0; if: 5231; case: 6546;
Number: 1; if: 24566; case: 22647;
Number: 2; if: 23597; case: 22243;
Number: 3; if: 31683; case: 29458;
Number: 4; if: 51127; case: 29016;
Number: 5; if: 31886; case: 29061;
Number: 6; if: 31513; case: 28714;
Number: 7; if: 31786; case: 28620;
Number: 8; if: 31776; case: 28919;
Number: 9; if: 31904; case: 29244;
Number: 10; if: 32425; case: 29664;
Number: 11; if: 31117; case: 28366;
Number: 12; if: 32097; case: 28867;
Number: 13; if: 31611; case: 28141;
Number: 14; if: 33479; case: 29676;
Number: 15; if: 33580; case: 29522;
Number: 16; if: 50382; case: 29407;
Number: 17; if: 33329; case: 29133;
Number: 18; if: 33596; case: 29043;
Number: 19; if: 39218; case: 34562;
Number: 20; if: 34180; case: 28986;
Number: 21; if: 34255; case: 29009;
Number: 22; if: 33630; case: 27863;
Number: 23; if: 35377; case: 29243;
Number: 24; if: 34797; case: 29131;
Number: 25; if: 35607; case: 28884;
Number: 26; if: 36327; case: 29578;
Number: 27; if: 35423; case: 29065;
Number: 28; if: 36542; case: 29335;
Number: 29; if: 36879; case: 29490;
Number: 30; if: 35878; case: 29060;
Number: 31; if: 36646; case: 28718;
Number: 32; if: 36722; case: 29118;
Number: 33; if: 35970; case: 28095;
Number: 34; if: 37538; case: 29156;
Number: 35; if: 38570; case: 29495;
Number: 36; if: 38164; case: 29271;
Number: 37; if: 37878; case: 28412;
Number: 38; if: 38150; case: 29236;
Number: 39; if: 56391; case: 29382;
Number: 40; if: 38712; case: 28866;
Number: 41; if: 39742; case: 29639;
Number: 42; if: 39191; case: 29015;
Number: 43; if: 38907; case: 28566;
Number: 44; if: 39041; case: 28056;
Number: 45; if: 40340; case: 28621;
Number: 46; if: 40109; case: 28942;
Number: 47; if: 39556; case: 28217;
Number: 48; if: 40690; case: 29233;
Number: 49; if: 40788; case: 44688;
Number: 50; if: 41130; case: 28763;
Number: 51; if: 41332; case: 28204;
Number: 52; if: 41438; case: 29065;
Number: 53; if: 42243; case: 29456;
Number: 54; if: 43001; case: 29435;
Number: 55; if: 41579; case: 28384;
Number: 56; if: 42199; case: 28714;
Number: 57; if: 42592; case: 28779;
Number: 58; if: 42065; case: 28445;
Number: 59; if: 43884; case: 29505;
Number: 60; if: 60339; case: 29813;
Number: 61; if: 43706; case: 28976;
Number: 62; if: 48062; case: 32434;
Number: 63; if: 43802; case: 28126;
Number: 64; if: 45031; case: 29376;
Number: 65; if: 48779; case: 33106;
Number: 66; if: 43914; case: 28312;
Number: 67; if: 45479; case: 29204;
Number: 68; if: 45589; case: 28597;
Number: 69; if: 44685; case: 28006;
Number: 70; if: 63052; case: 29261;
Number: 71; if: 46060; case: 28876;
Number: 72; if: 46894; case: 29504;
Number: 73; if: 47547; case: 29568;
Number: 74; if: 46261; case: 29076;
Number: 75; if: 47006; case: 28954;
Number: 76; if: 47176; case: 28883;
Number: 77; if: 46175; case: 28063;
Number: 78; if: 47973; case: 28995;
Number: 79; if: 48552; case: 29471;
Number: 80; if: 63565; case: 28460;
Number: 81; if: 48263; case: 28755;
Number: 82; if: 48757; case: 28686;
Number: 83; if: 58056; case: 39099;
Number: 84; if: 49034; case: 29012;
Number: 85; if: 49800; case: 29524;
Number: 86; if: 49821; case: 29114;
Number: 87; if: 49565; case: 29174;
Number: 88; if: 49211; case: 28151;
Number: 89; if: 50038; case: 46191;
Number: 90; if: 51031; case: 29290;
Number: 91; if: 49965; case: 28308;
Number: 92; if: 50858; case: 28995;
Number: 93; if: 50861; case: 29106;
Number: 94; if: 51611; case: 28811;
Number: 95; if: 51044; case: 28643;
Number: 96; if: 51846; case: 28945;
Number: 97; if: 52293; case: 29051;
Number: 98; if: 52979; case: 29463;
Number: 99; if: 68037; case: 28276;
Average ticks
if: 42928
case: 29964
и результат с оптимизациями
sheridan@amd-gentoo tests % g++ if-case.cpp -O2 -o si; ./si
Number: 0; if: 4209; case: 3988;
Number: 1; if: 23017; case: 20805;
Number: 2; if: 22176; case: 21267;
Number: 3; if: 29033; case: 27017;
Number: 4; if: 28951; case: 26887;
Number: 5; if: 29551; case: 26269;
Number: 6; if: 29417; case: 26552;
Number: 7; if: 30218; case: 26902;
Number: 8; if: 30245; case: 27421;
Number: 9; if: 30333; case: 26417;
Number: 10; if: 30684; case: 27439;
Number: 11; if: 29689; case: 25796;
Number: 12; if: 30690; case: 26389;
Number: 13; if: 30716; case: 26126;
Number: 14; if: 30436; case: 26980;
Number: 15; if: 31014; case: 27260;
Number: 16; if: 31928; case: 27430;
Number: 17; if: 31167; case: 27161;
Number: 18; if: 31588; case: 26756;
Number: 19; if: 37303; case: 32483;
Number: 20; if: 32075; case: 26611;
Number: 21; if: 32329; case: 27356;
Number: 22; if: 31538; case: 25823;
Number: 23; if: 33278; case: 26851;
Number: 24; if: 32300; case: 26452;
Number: 25; if: 32848; case: 26228;
Number: 26; if: 32981; case: 52079;
Number: 27; if: 32921; case: 27266;
Number: 28; if: 33344; case: 26495;
Number: 29; if: 33787; case: 27166;
Number: 30; if: 33133; case: 26348;
Number: 31; if: 33285; case: 26431;
Number: 32; if: 34007; case: 26244;
Number: 33; if: 32537; case: 25790;
Number: 34; if: 34048; case: 27169;
Number: 35; if: 34659; case: 27186;
Number: 36; if: 34496; case: 26677;
Number: 37; if: 34159; case: 26197;
Number: 38; if: 34361; case: 26835;
Number: 39; if: 34949; case: 26227;
Number: 40; if: 34886; case: 27272;
Number: 41; if: 35556; case: 26942;
Number: 42; if: 34803; case: 26778;
Number: 43; if: 35009; case: 26524;
Number: 44; if: 35071; case: 25744;
Number: 45; if: 35387; case: 26404;
Number: 46; if: 35842; case: 27084;
Number: 47; if: 35195; case: 26448;
Number: 48; if: 36233; case: 26799;
Number: 49; if: 35613; case: 26100;
Number: 50; if: 36303; case: 26822;
Number: 51; if: 35928; case: 26774;
Number: 52; if: 36706; case: 27083;
Number: 53; if: 36935; case: 27179;
Number: 54; if: 37230; case: 26991;
Number: 55; if: 36007; case: 25683;
Number: 56; if: 36930; case: 27034;
Number: 57; if: 36650; case: 26674;
Number: 58; if: 67032; case: 25945;
Number: 59; if: 37737; case: 27212;
Number: 60; if: 38216; case: 27033;
Number: 61; if: 37665; case: 26877;
Number: 62; if: 42001; case: 30204;
Number: 63; if: 38155; case: 26088;
Number: 64; if: 38277; case: 27103;
Number: 65; if: 43066; case: 31050;
Number: 66; if: 38204; case: 26345;
Number: 67; if: 39259; case: 26782;
Number: 68; if: 38724; case: 26011;
Number: 69; if: 38374; case: 26122;
Number: 70; if: 39079; case: 26555;
Number: 71; if: 39282; case: 27073;
Number: 72; if: 39809; case: 27182;
Number: 73; if: 40076; case: 53457;
Number: 74; if: 39444; case: 26076;
Number: 75; if: 39822; case: 26332;
Number: 76; if: 40346; case: 26030;
Number: 77; if: 149570; case: 25790;
Number: 78; if: 40716; case: 26751;
Number: 79; if: 40952; case: 27367;
Number: 80; if: 39761; case: 25574;
Number: 81; if: 40754; case: 26246;
Number: 82; if: 40939; case: 26086;
Number: 83; if: 49030; case: 34838;
Number: 84; if: 41213; case: 27083;
Number: 85; if: 41758; case: 27152;
Number: 86; if: 42409; case: 27123;
Number: 87; if: 43000; case: 53662;
Number: 88; if: 42675; case: 26538;
Number: 89; if: 43145; case: 26614;
Number: 90; if: 44291; case: 27052;
Number: 91; if: 43460; case: 26231;
Number: 92; if: 43756; case: 26715;
Number: 93; if: 43953; case: 26526;
Number: 94; if: 44467; case: 26277;
Number: 95; if: 44110; case: 26795;
Number: 96; if: 44143; case: 27034;
Number: 97; if: 44582; case: 26810;
Number: 98; if: 44488; case: 27128;
Number: 99; if: 43353; case: 25541;
Average ticks
if: 38416
case: 28164
Но что примечательно — с -O3 становится веселее:
sheridan@amd-gentoo tests % g++ if-case.cpp -O3 -o si; ./si
Number: 0; if: 755; case: 609;
Number: 1; if: 551; case: 369;
Number: 2; if: 581; case: 92;
Number: 3; if: 693; case: 95;
Number: 4; if: 935; case: 321;
Number: 5; if: 993; case: 84;
Number: 6; if: 1075; case: 62;
Number: 7; if: 1150; case: 51;
Number: 8; if: 1226; case: 51;
Number: 9; if: 1426; case: 36;
Number: 10; if: 1528; case: 39;
Number: 11; if: 1985; case: 39;
Number: 12; if: 1831; case: 357;
Number: 13; if: 2030; case: 39;
Number: 14; if: 2133; case: 39;
Number: 15; if: 2337; case: 39;
Number: 16; if: 2732; case: 39;
Number: 17; if: 2511; case: 39;
Number: 18; if: 2730; case: 36;
Number: 19; if: 2834; case: 39;
Number: 20; if: 3037; case: 183;
Number: 21; if: 3137; case: 39;
Number: 22; if: 3338; case: 36;
Number: 23; if: 3530; case: 39;
Number: 24; if: 3512; case: 39;
Number: 25; if: 3730; case: 36;
Number: 26; if: 3912; case: 39;
Number: 27; if: 4135; case: 36;
Number: 28; if: 4131; case: 39;
Number: 29; if: 4236; case: 39;
Number: 30; if: 4410; case: 39;
Number: 31; if: 4612; case: 39;
Number: 32; if: 4811; case: 39;
Number: 33; if: 4812; case: 39;
Number: 34; if: 5011; case: 39;
Number: 35; if: 5230; case: 39;
Number: 36; if: 5354; case: 36;
Number: 37; if: 5411; case: 39;
Number: 38; if: 5512; case: 39;
Number: 39; if: 35450; case: 59;
Number: 40; if: 33589; case: 84;
Number: 41; if: 64275; case: 78;
Number: 42; if: 33887; case: 57;
Number: 43; if: 33161; case: 33;
Number: 44; if: 33144; case: 83;
Number: 45; if: 33733; case: 70;
Number: 46; if: 34546; case: 46;
Number: 47; if: 36962; case: 95;
Number: 48; if: 34618; case: 46;
Number: 49; if: 34053; case: 52;
Number: 50; if: 35044; case: 84;
Number: 51; if: 34377; case: 62;
Number: 52; if: 35185; case: 57;
Number: 53; if: 35544; case: 68;
Number: 54; if: 36047; case: 70;
Number: 55; if: 34518; case: 73;
Number: 56; if: 35847; case: 84;
Number: 57; if: 35945; case: 78;
Number: 58; if: 35175; case: 70;
Number: 59; if: 36113; case: 62;
Number: 60; if: 36823; case: 55;
Number: 61; if: 36445; case: 46;
Number: 62; if: 40863; case: 44;
Number: 63; if: 36349; case: 33;
Number: 64; if: 37601; case: 46;
Number: 65; if: 41454; case: 33;
Number: 66; if: 39935; case: 59;
Number: 67; if: 37331; case: 33;
Number: 68; if: 37041; case: 166;
Number: 69; if: 36971; case: 33;
Number: 70; if: 38330; case: 33;
Number: 71; if: 38005; case: 33;
Number: 72; if: 38024; case: 51;
Number: 73; if: 38669; case: 64;
Number: 74; if: 71977; case: 33;
Number: 75; if: 38371; case: 33;
Number: 76; if: 38512; case: 171;
Number: 77; if: 37720; case: 33;
Number: 78; if: 39114; case: 33;
Number: 79; if: 39354; case: 33;
Number: 80; if: 38091; case: 46;
Number: 81; if: 39491; case: 33;
Number: 82; if: 38923; case: 33;
Number: 83; if: 47743; case: 66;
Number: 84; if: 39830; case: 195;
Number: 85; if: 40184; case: 33;
Number: 86; if: 40256; case: 33;
Number: 87; if: 40155; case: 33;
Number: 88; if: 39334; case: 33;
Number: 89; if: 41203; case: 33;
Number: 90; if: 41140; case: 33;
Number: 91; if: 43434; case: 33;
Number: 92; if: 40837; case: 33;
Number: 93; if: 40885; case: 33;
Number: 94; if: 41071; case: 33;
Number: 95; if: 41320; case: 62;
Number: 96; if: 43622; case: 26;
Number: 97; if: 41465; case: 46;
Number: 98; if: 42022; case: 33;
Number: 99; if: 43249; case: 293;
Average ticks
if: 25858
case: 945