Как написать этот код с ассемблерным кодом? - PullRequest
1 голос
/ 19 сентября 2009

Я хочу изменить этот код на ассемблер, работая на Mac, как это сделать?

while (a --)
{
    *pDest ++ += *pSrc ++;
}

Ответы [ 6 ]

6 голосов
/ 19 сентября 2009

Это Intel Mac и на iPhone. Я работаю над программой, которая использует этот код в потоке, и поток всегда делает такие вещи, иногда он зависает, поэтому мне интересно, не потому ли это, что вычисления слишком тяжелы для iPhone.

Нет, ваша проблема не имеет ничего общего с этим кодом. Пусть компилятор сделает свою работу и оптимизирует это. Ваша проблема в другом месте. Похоже, у вас есть состояние гонки или тупиковая ситуация между потоками. Я не могу психически отладить вашу проблему без дополнительной информации, но могу точно сказать, что вы лаете не на то дерево.

2 голосов
/ 21 сентября 2009

Так это для руки? (Iphone?). Каков размер этих указателей (байтов, полуслов, слов и т. Д.?), Возникают ли у вас проблемы с выравниванием (копирование слов на несловесной границе)? Если это байты, то да, сгенерированный код, вероятно, мучительно медленный, оптимизатор не может сделать с ним слишком много. Где это тебя оставляет? Вы получаете то, что вы получаете.

Вот пример:

    mov ip, #0
.L3:
    ldrb    r3, [r0, ip]    @ zero_extendqisi2
    ldrb    r2, [r1, ip]    @ zero_extendqisi2
    add r3, r3, r2
    strb    r3, [r1, ip]
    add ip, ip, #1
    cmp ip, r4
    bne .L3

Поскольку в вашем коде подсчитывались указатели, компилятор добавил инструкцию, которая ему не нужна.

    sub     ip, rx, #1
.L3:
    ldrb    r3, [r0, ip]    @ zero_extendqisi2
    ldrb    r2, [r1, ip]    @ zero_extendqisi2
    add r3, r3, r2
    strb    r3, [r1, ip]
    subs    ip, ip, #1
    bne .L3

Поскольку бит переноса не используется, мне интересно, есть ли способ загрузить слово и выполнить сложение по словам, выполняя по одному слову за раз.

load 0xnnmmoopp
load oxqqrrsstt

замаскируйте один из них, чтобы гарантировать отсутствие проблем с переносом

0xnnmmoopp -> 0xn0mmo0pp

добавить

0xgghhiikk = 0xn0mmo0pp + 0xqqrrsstt

затем сохраните hh и kk как байты

Вы должны вернуться к исходному повреждению байтов mm и pp, заново выполнить добавление и сохранить байты gg и ii.

Чтение двух слов должно быть значительно быстрее, чем чтение четырех байтов, если вы сохраняете все вышеперечисленное в регистрах и делаете хранилище слов вместо четырехбайтовых хранилищ, что сэкономит немного больше времени.

Вам нужно будет сохранить много регистров в стек, так что это будет стоить вам, поэтому вы не хотите делать это для небольших значений (скажем, меньше 10).

Во всяком случае, есть о чем подумать. Просто удаление одной строки кода в приведенном выше ассмблере должно быть заметно для длительных прогонов.

EDIT:

На самом деле та модификация, которую я сделал для вывода компилятора, была нарушена. Это больше похоже на это:

    mov  ip, ra
.L3:
    subs ip, ip, #1
    ldrb r3, [r0, ip]   
    ldrb r2, [r1, ip]   
    add  r3, r3, r2
    strb r3, [r1, ip]
    bne  .L3
2 голосов
/ 19 сентября 2009

Предполагая, что рассматриваемые массивы имеют разумную длину и в зависимости от типов pDest и pSrc, вы можете получить разумное ускорение с помощью инструкций NEON на ARMv7 (iPhone 3GS и новый Touch ) и с помощью SSE на Intel.

Конкретный код и то, какое ускорение вы можете получить, будет зависеть от типа данных в массивах источника и назначения, какого выравнивания вы гарантируете по адресам массива и каково распределение типичных длин в массиве. массивы это как.

Как всегда, ничего из этого не стоит делать, если у вас нет следа Акулы, показывающего, что этот цикл занимает значительную часть вашего времени выполнения. Если вы выполняете настройку производительности на уровне приложений на Mac или iPhone и не используете Shark или Instruments, вы делаете это неправильно.

Если массивы с плавающей точкой, вы можете получить хорошо настроенный векторный код на Intel Mac, включив Accelerate.framework и используя функцию vDSP_vadd (). Код сборки не требуется.

Если у вас есть доступ к выступлениям на WWDC 2008 года, Эрик Постпишил сделал хороший доклад об основных методах векторизации, в которых он рассмотрел написание векторного кода для обработки именно этого цикла (в случае, когда pSrc и pDest являются массивами одинарной точности) в Intel, хотя для простоты он использовал C с векторными характеристиками вместо ASM.

2 голосов
/ 19 сентября 2009

Фактические инструкции на ассемблере будут отличаться, но вот псевдокод, который можно легко перевести на ассемблер.

обратите внимание, что * 4, потому что я предполагаю, что вы переводите целые числа. Это будет варьироваться в зависимости от размера передаваемых данных.

incrementor = 0 ;really easy
top:
jump to bottom if a equals 0        ;jump if zero is the intel instruction here.
memoryDest[incrementor*4] = memorySrc[incrementor*4] ;this will be a bit messy, you'll probably need some temp variables
incrementor += 1  ;dead easy
jump to top: ;goto. PLEASE DON'T CITE 'CONSIDERED HARMFUL`, THIS IS ASM!!!!11ONEONE
bottom:
1 голос
/ 19 сентября 2009

Несколько стековых выстрелов покажет, действительно ли это то место, где вы проводите время.

Если это , развертывание цикла может помочь, как в:

while (a >= 8){
    pDest[0] += pSrc[0];
    pDest[1] += pSrc[1];
    pDest[2] += pSrc[2];
    pDest[3] += pSrc[3];
    pDest[4] += pSrc[4];
    pDest[5] += pSrc[5];
    pDest[6] += pSrc[6];
    pDest[7] += pSrc[7];
    pDest += 8;
    pSrc += 8;
    a -= 8;
}
// followed by your loop

Вы можете написать код на ассемблере, но, вероятно, это будет не намного лучше.

0 голосов
/ 19 сентября 2009

Вы говорите, что разрабатываете для iPhone и пытаетесь улучшить скорость. Похоже, вы пытаетесь скопировать блок памяти, для которого вы, вероятно, хотите использовать memcpy (dest, src, size) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...