Код (Text): #define NUM 256*1024*1024 double calc5() { double pi = 0.0; double two = 2.0; int i = 0; double four = 4.0; _asm { mov ecx, 0; fld two; fld1; fld pi; labela: fld st(2); mov i, ecx; fimul i; fadd st,st(2); fld st(2); fxch; fdivp st(1),st; mov eax,ecx; and eax,1; cmp eax,1; jne Parity; // нечетно fsubp st(1),st; jmp endec; Parity: // четно faddp st(1),st; endec: inc ecx; cmp ecx, NUM; jl labela; fmul four; fstp pi; } return pi; }
Код (Text): mov eax, ecx and eax, 1 Код (Text): test ecx, 1 А, вообще, разворот вдвое уберёт ветвление внутри цикла
Переменную цикла можно на уменьшение забить, а не на увеличение. Инетересно было бы ещё на формулу самих вычислений поглядеть, может быть она не очень рациональна. Вообще я бы на си на писал и поглядел))) При таком раскладе, компилятор может неплохой код даст.
Ага можно вообще без ветвления. код, inc(ecx), код, inc(ecx), jl Только это скорости не прибавляет. Пробовал. Тогда ответ не верный получается. Так я и написал сначала на си. А потом решил обыграть компилятор. Нифига. Код мой выполняется с той же скоростью...
Код (Text): mov ecx, NUM fldz fld1 fld1 fadd st(1), st jmp entr labela: fadd st, st(1) entr: fld1 fdiv st, st(1) faddp st(3), st dec ecx jz labelb fadd st, st(1) fld1 fdiv st, st(1) fsubp st(3), st dec ecx jnz labela labelb: fstp st(0) fstp st(0) fmul four fstp pi Хотя выигрыша почти нет Зато размер Код (Text): fldpi fstp pi
Код (Text): double calc5() { double pi = 0.0; double four = 4.0; int i = 1; _asm { mov ecx, NUM fldz labela: fld1 fidiv i add i, 2 faddp st(1), st sub ecx, 2 fchs jnz labela fmul four fstp pi } return pi; }
1/1 - 1/3 + 1/5 - 1/7 + 1/9 - ... = arctg 1 Неправда! Верный Только скорость от этого падает с ~2 до ~4с Если вместо i забить [eax], размер цикла ровно 16 байт В C нема align?
Циклы выравивать некоторые компиляторы могут, не которые нет. Если для данных, то в вижаке align есть....
Чё не так? Ошибка в результате? У меня правильно считал. Ну, а не идентичен - что конкретно не нравицца?
Прошу прощения, но то что в тегах code я частично не вижу он причине отсутствия скролбара на дочерних окнах, а посему прошу пояснить мне что призван делать приведенный код?
Да в результате. Возьми мой оригинальный код и свой. Сделай NUM = 10, 100, 1000 и посмотри на результат. Твой код аналогичен NUM/2.
Можно решить проблему с чередованием знаков и заодно сократить число делений, если обрабатывать пары слагаемых 1/(x+2)-1/(x+4) = 2/(x+2)*(x+4) - тут еще и 2 за скобку вынести Приимерно так: Код (Text): mov ecx,Num mov edx,ecx shr ecx,1 fldz //sum fld1 fadd st0,st0 //2 fld st0 fadd st0,st0 //4 fld1 fchs //x = -1 @loop: fld st0 fadd st0,st2 //x+4 fxch s0,st1 //x'=x+4 fadd st0,st3 //x+2 fmul st0,st1 //(x+2)*(x+4) fld1 fdivrp //1/(x+2)*(x+4) faddp st4,st0 //sum+=1/(x+2)*(x+4) dec ecx jnz @loop fld st3 fadp st4,st0 //sum=sum*2 and edx,1 //проверка Num на нечетность jz @skip fadd st0,st2 //x+2 fld1 fdivrp //1/(x+2) fadd st3,st0 @skip: fstp st0 fstp st0 fstp st0 fstp pi