Всем привет. В Delphi есть процедура Move( const Source; var Dest; count : Integer ); обычно с её помощью копируют данные в буфер вершин. На всякий случай привожу её код: Код (Text): asm { ->EAX Pointer to source } { EDX Pointer to destination } { ECX Count } PUSH ESI PUSH EDI MOV ESI,EAX MOV EDI,EDX MOV EAX,ECX CMP EDI,ESI JA @@down JE @@exit SAR ECX,2 { copy count DIV 4 dwords } JS @@exit REP MOVSD MOV ECX,EAX AND ECX,03H REP MOVSB { copy count MOD 4 bytes } JMP @@exit @@down: LEA ESI,[ESI+ECX-4] { point ESI to last dword of source } LEA EDI,[EDI+ECX-4] { point EDI to last dword of dest } SAR ECX,2 { copy count DIV 4 dwords } JS @@exit STD REP MOVSD MOV ECX,EAX AND ECX,03H { copy count MOD 4 bytes } ADD ESI,4-1 { point to last byte of rest } ADD EDI,4-1 REP MOVSB CLD @@exit: POP EDI POP ESI end; Будьте любезны и скажите, если я буду использовать вместо этой процедуры цикл: Код (Text): for i: 100 downto 0 do begin VertexPointer(A)^ := Vertex[i]; Inc(Cardinal(A), VertexSize); end; На сколько сильно я проиграю в скорости записи данных в видеопамять? Дело в том, что мне нужно организовать доступ ко всему залоченному буферу, но поменять нужно лишь некоторое число вершин, но время от времени буфер может быть полностью переписан. Вот собственном мой код для записи данных в буфер. Можно ли его усовершенствовать, чтоб он был быстрее и какие способы для этого существуют. Код (Text): procedure TBufferMemory.SetItemValue(Y, X: Uint32; const Value: Pointer); begin if FFirstAllocatedElement = nil then Exit; if not(Y = FRowNumberInMatrix) then begin { Если необходимо сделать сдвиг строки элементов } FRowNumberInMatrix := Y; FHorisontalPointer := FFirstAllocatedElement; inc(Uint32(FHorisontalPointer), Y * FSizeOfHorisontalLine); FVerticalPointer := FHorisontalPointer; FColumnNumberInMatrix := 0; end; if X = FColumnNumberInMatrix + 1 then begin { Записать данные в следующую ячейку памяти } inc(FColumnNumberInMatrix); inc(Uint32(FVerticalPointer), FSizeOfOneElement); end else if X = FColumnNumberInMatrix - 1 then begin { Записать данные в предыдущую ячейку памяти } dec(FColumnNumberInMatrix); dec(Uint32(FVerticalPointer), FSizeOfOneElement); end else if not(X = FColumnNumberInMatrix) then begin { Записать данные в произвольную ячейку отличную от предыдущей } FColumnNumberInMatrix := X; FVerticalPointer := FHorisontalPointer; inc(Uint32(FVerticalPointer), X * FSizeOfOneElement); end; Move(Value^, FVerticalPointer^, FSizeOfOneElement); end;
35 человек смотрели тему и ни одного комментария. У меня сложилось такое впечатление: или я неправильно задал вопросы или у прочитавших нет ответов.
PavDimka Ещё тут мало дельфистов, соответсвенно мне например это и скомпилить нечем чтобы глянуть подробности и вникать в такой код лень. Поэтому могу только посоветовать применить rdtst для сравнительных замеров, поищи по форуму это тут часто обсуждалось.
Сделал тест на 1000 проходов. В среднем полное копирование в цикле на 30-35 % медленнее. Помогите мне хоть чуть-чуть разогнать мою процедуру SetItemValue. Существует ли такой способ написания процедуры на asm, чтоб она работала быстрее, чем после обработки её дельфийским компилятором?
А почему вы думаете что вы пишете непосредственно в видеопамять? Не указано что за буфер, вижу только просто кусок памяти в который пытаетесь произвольно записать что-то. существует, только смотря что под этим подразумевать. Если замена кучи специфических дельфовых функов десятком mmx команд, то выигрыш будет заметен. Если теже самые простые функции пытататься написать теми же командами ассемблера, в чем тогда смысл?
Указатель получен при использовании функции Lock в IDirect3DvertexBuffer9. я конечно получаю указатель не на видеостраницу, но на участок видеопамяти под данные для вершин. По крайней мере, если используется аппаратная поддержка при инициализации девайса это должно быть правдой. Хочу чтоб выигрыш стал заметным, но писать на asm не умею, но чуть-чуть понимаю.
напишите весь нужный кусок на С (без ++), скомпильте интел С. поиграйтесь с флагами. если вы будете выжимать на асме не зная последнего - будет только хуже.
и еще одно - переход в функцию это много тактов. если вы выжимаете, то надо уменьшать количество переходов и вызовов и количество переменных. это в общем случае. нюансов тут хватает. скорей всего даже у вас провал не в этом месте. сколько вы вершин копируете? так много, что аж комп тормозит? а сколько оно отрисовываться тогда должно?
Спасибо за совет. Тут дело не в количестве и тормозах, а в задаче. Мне нужно организовать доступ к отдельным элементам буфера вершин. В тот момент, когда буфер заблокирован, а в нём уже содержатся данные, нужно поменять некоторые вершины. Сейчас это реализовано в коде SetItemValue. Источником данных служит таблица с вершинами [0,0,xmax,ymax]. Из таблицы берется указатель на вершину заданного размера из строки Y, колонки X и копируется в буфер вершин. Внутри процедуры реализован механизм перехода от начала буфера вершин до начала координат вершин из строки Y. Начало строки Y = размер вершины * номер строки + начало данных. Потом производится переход к вершине из колонки X. Координата вершины = Начало строки Y + размер вершины + X. Запись и выход. Алгоритм содержит проверки: есль ли переход к новой строке? Новая координата X меньше или больше на единицу предыдущей координаты? Это специальные случаи.
Ого! Как забавно, порой вспомнить о том, какие вопросы задавались месяц назад. Задача оптимизации алгоритма визуализации потока данных решена и протестирована. Общее увеличение производительности составляет порядка 10 %. Пропускная способность мультимедиа потока в формате 2D для графического интерфейса Direct3D9 возросла почти в 3 раза, однако, для ряда задач по визуализации тригонометрических функций и иных линейных уравнений увеличилась в 25 раз. Возможен вывод сложных двумерных графов с множественной зависимостью при частоте обновления приближенной к частоте регенерации экрана. Кто-нибудь знает, как правильно лицензировать программный код?