PDA

Просмотр полной версии : memcpy|быстрая пересылка данных



NovaStorm
01.11.2013, 16:21
Допустим нам надо перебросить данные (несколько кб) из одной области памяти(их несколько) в другую(а вот назначение постоянно или,если уж совсем идеально, пара-тройка адресов) и сделать это побыстрее, а памяти потратить на процедуру поменьше(килов до 4х отсилы).
Какие у нас пути?..
1) Если хранить данные внутри блоков ld rr,NN : push rr, получим наибыстрейшую загрузку(так ли это?) в 10.5 тактов на байт и эпический жор памяти. Врядли применимо в реальных проектах.
2) портянка из


ld sp,#src
pop af
pop bc
pop de
pop hl
exx
pop bc
pop de
pop hl
ld sp,#dest
push hl
push de
push bc
exx
push hl
push de
push bc
push af

даст 12.5 тактов на байт, но сожрёт много памяти, а источник выбрать не получится. =\
3) портянка из pop hl:ld hl,(NN). Удовлетворяет и скоростью и выбором источника, но память жрёт тоже неприемлемо.
4) красивая макра - хорошая замена LDIR'у, стек не трогает - почти 16t/b и немного памяти, но я хочу быстрее =(


macro ldirf
xor a
sub c
and 128-1
add a,a
ld ($+4),a
jp 1f
align 256
1
dup 128
ldi
edup
jp pe,1b
endm

На основе варианта №2 накодил самомодифицирующийся цикл с ~15t/b размером даже меньше варианта №4, можно ли ЕЩЁ быстрее? (Да, пока есть память, можно часть переслать по №3, часть ещё как-то, но вопрос не в этом =))

Hacker VBI
01.11.2013, 16:40
второй вариант в цикле

NovaStorm
01.11.2013, 16:49
Hacker VBI, у тебя ведь хватило терпения дочитать до конца? =)
Я так и сделал, но вышло ~15t/b, может я это сделал криво и есть лучшая реализация?

introspec
01.11.2013, 16:55
NovaStorm, буквально этот вопрос разжевали неделю назад на WoS: http://www.worldofspectrum.org/forums/showthread.php?t=45321
HackerVBI совершенно прав.

NovaStorm
01.11.2013, 17:03
it takes about 13,9 tstates for a byte copy
Во, вот этото что надо.
Я пролетел на INC IXH, INC IYH.
А так этот вопрос-то и у нас обсуждали, но до таких результатов дело не дошло.

Hacker VBI
01.11.2013, 19:01
NovaStorm, приходится колебаться между скоростью и обьёмом занимаемой памяти. поэтому рекомендую таки тратить капельку тактов на отработку обвязки djnz

alone
02.11.2013, 09:10
Если хранить данные внутри блоков ld rr,NN : push rr, получим наибыстрейшую загрузку(так ли это?) в 10.5 тактов на байт
Зависит от самих данных. Не все ld в ld: push нужны. А какая задача? В текстовых листалках ld: push вполне юзабельно.

Lethargeek
02.11.2013, 12:38
3) портянка из pop hl:ld hl,(NN). Удовлетворяет и скоростью и выбором источника, но память жрёт тоже неприемлемо.
смотря где и для чего неприемлемо - емнип так в кустарной переделке под 128K игры Thanatos размотали сразу на весь экран

GM BIT
02.11.2013, 16:20
3) портянка из pop hl:ld hl,(NN).
:) улыбнуло

Откуда - источник, куда - приемник
Если источники разные а приемник один:
pop hl: ld (NN),hl

Если источник один а приемники разные:
ld hl,(NN): push hl

Если источник один, и приемник один:
ld hl,nn: push hl
либо
ld sp,nn1
pop hl,de,bc,af
ld sp,nn2
push af,bc,de,hl

Использовать дополнительно exx, ix, iy - это вата, не такой уж и выигрыш в скорости

В последнем случае возможна нехилая оптимизация если используются повторяющиеся байты
Быстрее наверное не получится, если не знаешь какие байты ты переносишь

Если короче то наверное последний вариант в цикле либо куча ldi (тоже как вариант)

NovaStorm
02.11.2013, 19:52
>улыбнуло
Ах, ну да...
Это чтобы вражьи агенты не пронюхали. А тут все свои всё поняли. =)
exx использовать стоит, тк организация цикла жрёт много, а тут за 4+4 такта получаем ещё немного регистров.
Уже заюзал процедурку, вроде всё пашет, щястя!