Эк тя расколбасило :lool: Вполне достаточно, чтобы обогнать третий вариант, от Adrax :P Бред :\ Еще раз бред. Увеличение работы с памятью не может добавить прироста.
AndNot Слушай, идиот, не упоминай при мне слово бред. Я понимаю, что для кулхацкеров неочевидна разница между movzx и mov , поэтому прежде чем писать такую [...], как "Увеличение работы с памятью", сначала попробуй, а потом будешь делать заявления.
to Cresta[/] Во первых. Я тебя где нибудь обзывал? Во вторых. Прежде чем что то называть [...], сам бы проверил, после этого ты бы так не говорил. Подумай о промахах кэша и как это скажется на производительности. В третьих. Я не говорил, что VC создает плохой код, я утверждаю что человек сделает лучше. Можем и проверить, только на более жизненных примерах, например альфа-наложение. И в четвертых. Если не нравится мой словарный запас, то составь список слов, которые можно употреблять в твоем присутствии. :-?
ИМХО для большого N: надо было взять код на С, проинициализировать array[] где надо нулями, внутренний цикл расписать на несколько переменных а внешний сократить во столько же раз, и откомпилировать gcc версии не ниже 4.1.x c опциями на максимальную оптимизацию. P.S. или для начала откомпилировать разными компиляторами и посмотреть
2 t00x Сейчас попробую gcc, спасибо за идею Насчёт использования либ... Скачал я GMP в исходниках, функи из mpn с аттшного синтаксиса на родной интеловский перевёл - а дальше ступор... Типы данных там очччень прикольно описаны: Функция принимает параметры типа x. Тип x описан в таком-то хедере, как массив переменных типа y количеством z. За y и z нужно лезть в другие хедеры, потом ещё и ещё...
Код, который работает в 3 раза быстрее самого быстрого из приведенных выше в этом топике С использованием reciprocal division. Код (Text): .data align 16 Len dd 1 align 16 array dw 1 dw 1000000 dup(0) ;-------------------------------------------------- factorial proc N:DWORD option prologue : none option epilogue : none push ebp push edi push esi push ebx xor ecx,ecx mov ebx,1 cmp dword ptr [esp+20],1 mov esi,Len mov ebp,3518437209 jb _end _ext: xor edi,edi align 16 _int: movzx eax,word ptr[array+edi*2] imul eax,ebx add ecx,eax mov eax,ecx mul ebp shr edx,13 imul eax,edx,10000 sub ecx,eax mov word ptr[array+edi*2],cx inc edi mov ecx,edx cmp edi,esi jc _int test edx,edx jnz _int inc ebx mov esi,edi cmp [esp+20],ebx jnc _ext mov Len,edi _end: pop ebx pop esi pop edi pop ebp retn 4 option prologue : prologuedef option epilogue : epiloguedef factorial endp Сравнение производилось на Athlon XP 2200+
2 cresta Преклоняюсь перед Вашим мастерством!!! Уму непостижимо! 150000! за 1:16!!! Ваш код божественен!!! В начале темы я утратил веру в Ассемблер, но Вы вернули мне её!!! Нет слов... Объясните мне, как Вы этого добились?! Дайте хоть ссылочку на основы этого reciprocal division!
Ээээ... Сворачиваю своё восхищённое словоизвержение... Код cresta я впихнул отдельной процедурой, вот так: Код (Text): format PE console include 'win32axp.inc' .data dllka db 'msvcrt.dll',0 name1 db 'scanf',0 scanf dd ? name2 db 'printf',0 printf dd ? inp db 'Input N:',0 d db '%d',0 d4 db '%04d',0 crlf db 13,10,0 N dd ? align 16 Len dd 1 align 16 array dw 1 dw 999999 dup 0 .code fuck: invoke LoadLibrary,dllka push eax invoke GetProcAddress,eax,name1 mov [scanf],eax pop eax invoke GetProcAddress,eax,name2 mov [printf],eax cinvoke printf,inp cinvoke scanf,d,N mov eax,[N] test eax,eax jl konets push eax call Factorial call Printt konets: cinvoke printf,crlf invoke ExitProcess,0 ;----------------------------------------------------- proc Factorial push ebp push edi push esi push ebx xor ecx,ecx mov ebx,1 cmp dword[esp+20],1 mov esi,[Len] mov ebp,3518437209 jb _end _ext: xor edi,edi align 16 _int: movzx eax,word[array+edi*2] imul eax,ebx add ecx,eax mov eax,ecx mul ebp shr edx,13 imul eax,edx,2710h sub ecx,eax mov word[array+edi*2],cx inc edi mov ecx,edx cmp edi,esi jc _int test edx,edx jnz _int inc ebx mov esi,edi cmp dword[esp+20],ebx jnc _ext mov [Len],edi _end: pop ebx pop esi pop edi pop ebp retn 4 endp ;-------------------------------------------------- proc Printt mov edi,[Len] movzx eax,word [array-2+edi*2] cinvoke printf,d,eax dec edi jz konets mtk: dec edi movzx ecx,word[array+edi*2] cinvoke printf,d4,ecx test edi,edi jnz mtk retn endp ;------------------------------------------------- .end fuck Быстро, слов нет... Но для любого N>7 получается искажённый результат N! Так что вопрос снова поднят... Есть ли более быстрые варианты ПРАВИЛЬНОГО вычисления факториала?