· Начало · Статистика · WASM.RU · Noir.Ru ·

 WASM Phorum (Оффлайн - 24.11.2003) —› WASM.ASSEMBLER —› SSE2

<< . 1 . 2 .

Посл.отвђт Сообщенiе


Дата: Окт 8, 2003 20:02:31

Max
проверить находится ли точка внутри треугольника с использованием SSE2 можно следующим образом:
struc triangle
{
  .x1 dd ?
  .x2 dd ?
  .x3 dd ?
  .y1 dd ?
  .y2 dd ?
  .y3 dd ?
}

test_pt:;(ptriangle +4,x +8,y +12)
;zf=1 если точка внутри треугольника
;и zf=0 в противном случае
  mov edx,[esp+4];ptriangle
  movd xmm0,[esp+8];|0|0|0|x|
  movd xmm1,[esp+12];|0|0|0|y|
  movdqu xmm2,[edx+triangle.x1];|U|x3|x2|x1|
  movdqu xmm3,[edx+triangle.y1];|U|y3|y2|y1|
  pshufd xmm0,xmm0,0;|x|x|x|x|
  pshufd xmm1,xmm1,0;|y|y|y|y|
  pshufd xmm4,xmm2,00001001b;|U|x1|x3|x2|
  pshufd xmm5,xmm3,00001001b;|U|y1|y3|y2|
  subps xmm4,xmm2;|U|x1-x3|x3-x2|x2-x1|
  subps xmm5,xmm3;|U|y1-y3|y3-y2|y2-y1|
  subps xmm1,xmm3;|U|y-y3|y-y2|y-y1|
  subps xmm0,xmm2;|U|x-x3|x-x2|x-x1|
  mulps xmm0,xmm5;|U|(x-x3)*(y1-y3)|(x-x2)*(y3-y2)|(x-x1)*(y2-y1)|
  mulps xmm1,xmm4;|U|(y-y3)*(x1-x3)|(y-y2)*(x3-x2)|(y-y1)*(x2-x1)|
  subps xmm0,xmm1;|U|d3|d2|d1|
  pmovmskb eax,xmm0;Это единственная команда SSE2.
       ;Чем бы ее заменить, чтобы и на атлонах работало?
  and eax,111h;проверяем знаки
  jz .exit
  xor eax,111h
.exit:
  ret 12


Дата: Окт 9, 2003 13:36:29

Black_mirror
Вот спасибо, процесс пошел... :)
Сначала вопрос...
movdqu загружает "Unaligned Double Quadword". Ничего, если ею загружается 4 single, а не 2 double?
То есть получается, что процу пофиг что загружать?

а теперь немного критики с моей стороны:
1. по условию задачи входные данные - это longint, т.е. их надо сначала преобразовывать к вещественному типу. Здесь же вычисления с ними ведутся как будто они single
2. опять же по условию, вычисления надо вести в double, тут все в single.
3. и опять же по условию :), если точка лежит на ребре она считается принадлежащей треугольнику. Здесь может получится d1=0, d2<0, d3<0, т.е. такой вариант не проверяется. Кстати, может получится d1=-0 (100..0B), d2>0, d3>0 - такой вариант не проверяется и в моем примере тоже, баг типа.


Дата: Окт 9, 2003 17:43:21

По моему эта инструкция просто пересылает 128 бит из памяти в регист или наоборот. А как они будут трактоваться это будет зависить от того, что мы с ними делаем.
Для такой задачи делать вычисления в double по моему не рационально. У нас всего 15(возможно 18) вычитаний и 6 умножений + проверка на знаки. Возможно что быстрее это на процессоре посчитать.


Дата: Окт 9, 2003 19:38:06

То есть получается, SSE эффективно только для обработки чисел небольшой размерности, типа 16 байт, 4 сингла...?
Может оно просто с double так погано работает?


Дата: Окт 10, 2003 12:03:22

Не думаю что SSE не эффективно использовать для double. Всетаки мы обрабатываем сразу по два числа, а не по одному на сопроцессоре. Но если входные данные int32 то зачем использовать большую точность? На моем процессоре целочисленное умножение выполняется 5 тактов. То есть вычислить значения d1-d3 можно за 6*5+18/2=39 тактов. Плюс 10 тактов на проверку знаков. Итого 50 тактов. В вашем коде SSE комманд я насчитал 39 штук. Насколько я знаю, спариваются они очень плохо. Можно узнать какова частота вашего процессора, и сколько треугольников вы обрабатывали для тестирования производительности, а то мс мало о чем говорят.


Дата: Окт 10, 2003 13:58:48

Вот вариант без SSE:
struc	tria
{
	.x1 dd ?
	.x2 dd ?
 	.x3 dd ?
	.y1 dd ?
	.y2 dd ?
	.y3 dd ?
}

ptin:;(ptria +4, x +8, y +12)
virtual at ebx
.t tria
end virtual
	xor ebp,ebp;здесь будут суммироваться знаки
	mov ebx,[esp+4]
;вычисление d
	mov edx,[esp+12]
	mov eax,[.t.x2]
	sub edx,[.t.y1]
	sub eax,[.t.x1]
	mov ecx,[esp+8]
	imul edx
	sub ecx,[.t.x1]
	mov esi,eax
	mov eax,[.t.y2]
	mov edi,edx
	sub eax,[.t.y1]
	imul ecx
	sub eax,esi
	sbb edx,edi
;проверка знака
	shl edx,1
	sbb ebp,0
	or eax,edx
	setnz cl
	add ebp,ecx
	
	mov edx,[esp+12]
	mov eax,[.t.x3]
	sub edx,[.t.y2]
	sub eax,[.t.x2]
	mov ecx,[esp+8]
	imul edx
	sub ecx,[.t.x2]
	mov esi,eax
	mov eax,[.t.y3]
	mov edi,edx
	sub eax,[.t.y2]
	imul ecx
	sub eax,esi
	sbb edx,edi

	shl edx,1
	sbb ebp,0
	or eax,edx
	setnz cl
	add ebp,ecx
	
	mov edx,[esp+12]
	mov eax,[.t.x1]
	sub edx,[.t.y3]
	sub eax,[.t.x3]
	mov ecx,[esp+8]
	imul edx
	sub ecx,[.t.x3]
	mov esi,eax
	mov eax,[.t.y1]
	mov edi,edx
	sub eax,[.t.y3]
	imul ecx
	sub eax,esi
	sbb edx,edi

	shl edx,1
	sbb ebp,0
	or eax,edx
	setnz cl
	add ebp,ecx

	xor eax,eax
	test ebp,3
	jnp .exit
    	inc eax
    .exit:
	ret 12

Если длина стороны больше 2^31-1 будет работать некорректно. На Athlon1900+ работает примерно за 60 тактов, вместе с кодом для вызова. Проверки на знаки нужно делать по другому, а то там сильная зависимость по данным. (Только вот как?) Возвращает eax=1 если точка попадает внутрь треугольника, и eax=0 если не попадает или попадает на сторону.


Дата: Окт 10, 2003 16:22:07 · Поправил: Max

Black_mirror
Но если входные данные int32 то зачем использовать большую точность?
Дело в том, что там используется перемножение. Если int32 * int32, то результат должет быть int64, иначе рискуем получить неверный результат (точнее правильный, но по модулю). Поэтому сравнивать мой пример с твоим строго говоря нельзя - они делают разные вещи.

Можно узнать какова частота вашего процессора, и сколько треугольников вы обрабатывали для тестирования производительности, а то мс мало о чем говорят.
Это я прогонял на P4 2.4GHz, DDR 512Mb 533MHz
[added: треугольников 1Е6]


Дата: Окт 10, 2003 17:01:23

Max
После умножения у нас три пары 64-битных чисел. И нужно сделать всего три 64-битных вычитания. В моем коде так и делается. Единственный случай когда программа выдает некорректный результат, это если длина проекции стороны треугольника на X или Y больше 2^31-1. Замеры производительности для 1E6 треугольников кода без SSE, показали что требуется 92 такта на треугольник. Примерно 58 ms. И 38 ms если данные помещаются в кеше. То есть все дело в пропускной способности памяти или шины. Ваш вариант с сопроцессором тратит 84 такта на треугольник. Похоже дело в том что умножение чисел с плавающей точкой выполняется быстрее чем целочисленное. Или в том что частота памяти у меня в 2 раза меньше 8)

<< . 1 . 2 .


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.075