Сейчас на форуме: (+5 невидимых) |
![]() |
eXeL@B —› Программирование —› Время выполнения команды lea |
Посл.ответ | Сообщение |
|
Создано: 23 июля 2007 15:08 · Личное сообщение · #1 Столкнулся с неоходимостью оптимизировать цикл. В профайлере видно что много времени расходуется на команду lea esi, [edi + ebx*04h] Вычисление адреса можно бы в принципе оптимизировать выкинув выражение за пределы цикла и просто потом прибавлять к edi 4. Только вот не знаю будет ли это лучше с точки зрения производительности. Целевой процессор неизвестен. Известно только что это современный. Вопрос, можно ли утверждать что прибавление 4 будет быстрее чем вышеприведенная команда? ![]() |
|
Создано: 23 июля 2007 15:10 · Личное сообщение · #2 |
|
Создано: 23 июля 2007 15:54 · Личное сообщение · #3 это первая команда цикла. так что если речь о распараллеливании этой и предыдущей команды по циклам, то это тут неприменимо. дальше вот такие команды 0x0041EFC7 8d349f 0x53 lea esi, [edi + ebx*04h] 0x0041EFCA 837df800 0x56 cmp dword ptr [ebp - 08h], +00h 0x0041EFCE 7407 0x5A je short +07h 0041EFD7h 0x0041EFD0 8b45f8 0x5C mov eax, dword ptr [ebp - 08h] 0x0041EFD3 3b06 0x5F cmp eax, dword ptr [esi] 0x0041EFD5 7577 0x61 jne short +77h 0041F04Eh ![]() |
|
Создано: 23 июля 2007 15:55 · Личное сообщение · #4 |
|
Создано: 23 июля 2007 21:00 · Поправил: s0larian · Личное сообщение · #5 egorovshura, сама инструкция проста, но в ней есть pointer dereference. Думаю что причина задержки в том что происходит page fault. Что у тебя там за указатель? (может ты идёшь по какому-то списку, в нём дикое количество элементов и многие элементы уже в swap... в этом случае тебе нужна алгоритмическая оптимизация а не ассемблерная) ![]() |
|
Создано: 24 июля 2007 00:42 · Личное сообщение · #6 алгоритмическая оптимизация себя уже исчерпала. остается только код. иду по массиву, но не по порядку, а со здвигами. задержек особенных нет. вернее я не смотрел, но не думаю что они есть. Просто этот код вызывается наибольшее количество раз, миллиарды раз и больше. вот и я подумал, что может замена lea на mov и add дадут выгрыш. например так: вместо loop: lea esi, [edi + ebx*04h] написать что-нить вроде mov esi, edi loop: shl ebx, 2 add esi, ebx ![]() |
|
Создано: 24 июля 2007 01:48 · Поправил: s0larian · Личное сообщение · #7 не думаю что ты чего-нить тут добьёшься просто асмом, т.к. задержка может быть только из-за работы с памятью - простое регистровое сложение/умножение будет сделано за один clock cycle, а операция с памятью уходит на по шине (если не попадает а cache) и стоит много циклов. Попробуй сделать так что б данных было меньше, что б переменные были ближе друг к другу и что бы динамически выделенные куски были выравнены на 16 байт. (То есть если ты имеешь, скажем, список то те данные которые ты смотришь должны быть в самом начале заголовка, каждая 32 битная переменная должна быть выравнена на 4 байта, сам заголовок должен быть выравнен на 16 байт...) Кста, ты уверен про алгоритмы? Что-то криво где-то если ты (линейно?) проверяешь миллиарды раз свои структуры. Тебе, может, надо хранить/искать по другому?... P.S. ну и test case создай, что б мерять можно было - кусок кода который крутит твою операцию с одними и теми же данными/размером десятки тысяч раз. ![]() |
|
Создано: 24 июля 2007 06:04 · Личное сообщение · #8 egorovshura пишет: Замена lea на mov и add дадут выгрыш. например Не думаю, читай мануалы А.Фога про оптимизацию. На васме периодически подымаются подобные темы и там есть ссылки тестовые проги, по которым удобно тестить куски кода (то, о чем тебе говорит s0larian). Но, как говорил один из местных знатоков, нет сейчас на современных процах никакого простора для оптимизации. И если ты оптимизируешь этот код для одного проца, не факт, что он будет так же хорошо работать на другом. ![]() |
|
Создано: 24 июля 2007 09:46 · Личное сообщение · #9 Это все верно, что нет простора... Тем не менее рискну заметить что ИМХО сама по себе эта lea вообще не при чем, ее результ используецца аж через 3 команды... Имхо, нужно пытацца избавляться от переходов. Вот, мне как-то раз удалось: else { for(I = 31; I >= 0; -- I) { pQuery->LFSR1 = pQuery->LFSR1 ^ ((Input >> I) & 1); pQuery->LFSR1 = (pQuery->LFSR1 >> 1) | (pQuery->LFSR1 << 31); if(pQuery->LFSR1 & 0x80000000) pQuery->LFSR1 ^= pQuery->Descriptor1; } Input = (Input >> 16) | (Input << 16); for(I = 31; I >= 0; -- I) { Output = Output | ((pQuery->LFSR1 & 1) << I); pQuery->LFSR1 = pQuery->LFSR1 ^ ((Input >> I) & 1); pQuery->LFSR1 = (pQuery->LFSR1 >> 1) | (pQuery->LFSR1 << 31); if(pQuery->LFSR1 & 0x80000000) pQuery->LFSR1 ^= pQuery->Descriptor1; } } return Output; Поменял на: ULONG Query0(QUERY *pQuery, ULONG Input) { ULONG Output = 0; ULONG tmpDescr[2] = {0, pQuery->Descriptor1}; _asm{ push esi push edi mov ebx, pQuery mov eax, [ebx].LFSR1 mov ecx, 32 NextLFSR1: ror eax, 1 xor eax, 0 sets dl movzx edx, dl xor eax, dword ptr tmpDescr[edx*4] dec ecx jnz NextLFSR1 xor edi, edi // Output mov ecx, 32 ... Кажется, на P4 выигрыш был даже больше чем на P3. ps А почему еще там много ссылок на [ebp-8]? Можно еще больше кода и немного описания? ----- The one derivative you manage is the one I abhore (c) Slipknot ![]() |
|
Создано: 24 июля 2007 10:13 · Личное сообщение · #10 Больше кода не имеет смысла приводить, потому как там очень замороченный алго и если привести еще кусочек, то появятся новые вопросы и т.д. Алгоритм оптимизировать тоже врядли удастся, потому как его до меня многие годы другие люди оптимизировали и сейчас это наилучший вариант того что возможно. Включая выравнивания в памяти. Вобщем похоже моя идея не оправдалась. Я хотел оптимизировать именно на асмовском уровне и независимо от целевого процессора. Всем спасибо. ![]() |
|
Создано: 25 июля 2007 19:43 · Личное сообщение · #11 |
|
Создано: 25 июля 2007 20:15 · Поправил: ssx · Личное сообщение · #12 |
|
Создано: 25 июля 2007 23:08 · Личное сообщение · #13 |
|
Создано: 26 июля 2007 00:24 · Личное сообщение · #14 |
![]() |
eXeL@B —› Программирование —› Время выполнения команды lea |