forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   C++ (http://forum.boolean.name/forumdisplay.php?f=22)
-   -   dword to float4 и обратно (http://forum.boolean.name/showthread.php?t=19690)

Samodelkin 12.02.2015 17:27

dword to float4 и обратно
 
Вопрос касается скорее инлайн ассемблера чем С/С++.
Какими инструкциями (в том числе доступными в расширениях процессора) можно максимально быстро выполнять конвертирование dword->float4 и обратно? В частности это нужно для софтварной имплементации выборки из текстуры, обсчёт на xmm регистрах и запись обратно в текстуру.

mr.DIMAS 13.02.2015 00:46

Ответ: dword to float4 и обратно
 
То есть тебе нужно что-то типа такого:
Код:

dword( byte1, byte2, byte3, byte4 )
byte1 -> float( 0...1 )
byte2 -> float( 0...1 )
byte3 -> float( 0...1 )
byte4 -> float( 0...1 )

и обратной запаковки в dword?

опиши подробнее, а то я ничего не понял.

Samodelkin 13.02.2015 03:26

Ответ: dword to float4 и обратно
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293208)
То есть тебе нужно что-то типа такого:
Код:

dword( byte1, byte2, byte3, byte4 )
byte1 -> float( 0...1 )
byte2 -> float( 0...1 )
byte3 -> float( 0...1 )
byte4 -> float( 0...1 )

и обратной запаковки в dword?

опиши подробнее, а то я ничего не понял.

Да именно так.

В SSE есть инструкция которая из 4 dword'ов может в 4 float'а сконвертить. Но побайтово SSE вроде не умеют работать (только с 4 байтами через инструкцию смешивания). Разделить dword на байты можно через РОН. Но копировать напрямую из РОН в xmm тоже вроде нельзя. Получается нужно загрузить в РОН, разделить на байты, снова записать в память и от туда загрузить в xmm. В целом записываться будет в кеш L1, так что не так много времени займет, но всё же лишние действия. Так или иначе сейчас у меня код написан на С++ и судя по листингу с ассемблером там очень много кода (т. к. делается через FPU), так что возможно удастся сделать быстрей.

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

mr.DIMAS 13.02.2015 16:24

Ответ: dword to float4 и обратно
 
А не проще ли забить на используемую память? Хранить сразу 4 флоата вместо dword? По памяти всего в 4 раза возрастает расход, но убирается ебля с преобразованиями.

Mr_F_ 13.02.2015 16:52

Ответ: dword to float4 и обратно
 
преобразование обычных регистров в XMM и обратно операция столь долгая, что может потеряться профит от самих SSE вычислений.

Samodelkin 13.02.2015 17:06

Ответ: dword to float4 и обратно
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293222)
А не проще ли забить на используемую память? Хранить сразу 4 флоата вместо dword? По памяти всего в 4 раза возрастает расход, но убирается ебля с преобразованиями.

Технически конечно проще. Такой вариант тоже рассматривается, пока нету больших проблем с занимаемой текстурами памяти и их можно увеличить. Но это также нагрузит и шину памяти, у неё тоже есть предел, ведь кол-во данных для чтения/записи увеличится в 4 раза. Хотя я раньше проводил тесты с выборкой одной текстуры, но сейчас в проекте используется больше чем одна и нагрузка может быть в разы больше. А в современных системах именно память самый медленный элемент. Так что все усилия по simd оптимизации и многопоточности могут упереться в скорость памяти.

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

Ещё, большие текстуры хуже умещаются в кеше. На самом деле с текстурами вообще такая проблема, что их выборка часто идёт хаотично, поэтому случаются кеш-промахи, здесь я буду пробовать создавать алгоритм наподобие mip-maping'а -- он не только улучшает визуализацию текстур (хотя в моём случае нужно применять и другие методы) но суть мип-мэпинга это подобрать разрешение текстуры таким образом чтобы оно совпадало с разрешением экрана, а это означает что выборка (при сканлайн-рендере) будет более упорядочена и префетчер лучше справится с кешированием данных текстуры. Однако в моём случае (речь о рейкастинге) рендер происходит вертикальными слайсами (столбцами) и это тоже негативно влияет на кеширование, как вариант можно сохранять данные текстур (и буферов) не построчно, а столбцами.

Ну короче тут много о чём можно рассуждать, но лучше подождать когда будут объективные данные с производительностью разных тестов.

Цитата:

Сообщение от Mr_F_
преобразование обычных регистров в XMM и обратно операция столь долгая, что может потеряться профит от самих SSE вычислений.

Ну то есть через кеш L1 это передается? Ну не то чтоб очень дорогая, например по сравнению с чтением из памяти без префетча это много быстрее. Чтение из L1 - около 3 циклов, из L2 около 20 циклов, из памяти - 200 циклов.
Сейчас я делаю инлайн целого ассемблерного блока в несколько страниц длиной, один раз загружаю в начале и записываю в конце, в целом удаётся уместить вычисления в 8 xmm регистров. В SSE есть ручное управление префетчем, так что можно и его попробовать если что.

Samodelkin 18.02.2015 22:55

Ответ: dword to float4 и обратно
 
Итак, первую версию велосипеда я сделал. Надо сказать что SIMD оптимизацию я представлял более оптимистично. Результат конечно есть, но это не разы, это где-то +30%, и это требует значительного пересмотра логики кода и структуры данных. Для сравнения DOD (Data Oriented Design) подход дал мне больше скорости чем ассемблирование (при этом он делает код более простым и понятным, в отличие от ассемблирования). Так или иначе это первая версия кодов, а у меня особого опыта ассемблирования тоже пока нет, возможно дальнейшие улучшения дадут больше результата. Ну и я думаю что поэтапное представление модернизации кодов будет интересно, чтобы наглядно увидеть какие проблемы пришлось решать.

Значит сейчас пойдет речь как раз о извлечении dword значения цвета в формате ARGB и преобразовании его в 4D вектор в формате float4( R, G, B, A ). Вот исходный материал:
Код:

texEnvironmentColor = cpTextureArray[ 0 ]->TexNearFast( { cWallTexCoordVecU[ 0 ], cWallTexCoordVecV[ 0 ] }, cpTextureArray[ 0 ]->ComputeLvl( cRayLenArray[ 0 ], cTwoTanAlpha, cFrameBufferSizeX, cWallWidth ) );
pMem->environmentColorVec0[ 0 ] = static_cast< uint8_t >( texEnvironmentColor >> 16 ) / 255.0f;
pMem->environmentColorVec0[ 1 ] = static_cast< uint8_t >( texEnvironmentColor >> 8 ) / 255.0f;
pMem->environmentColorVec0[ 2 ] = static_cast< uint8_t >( texEnvironmentColor ) / 255.0f;

Код конечно может быть перегружен, из-за того что я вырвал его из контекста, к сожалению сейчас основная цель у меня это сам проект, поэтому я просто не успеваю подготовить какие то сравнительные тесты и т. п. что по правилам следует делать в таких ситуациях. Значит первая строка это выборка из текстуры: не нужно вдаваться в подробности выборки, главное что в переменную texEnvironmentColor сохраняется dword значение цвета. Затем в трех последующих строках делается сдвиг и урезание до одного байта чтобы получить каждое значение цвета по очереди. Тут нужно заметить что альфа мне в данном случае не нужна и я не трачусь на неё, но вообще её получают тем же образом, если она есть в текстуре четвёртым каналом. Затем происходит деление каждого значения на 255.0f. Буква f указана явно (я её вообще всегда указываю) чтобы левый операнд сначала преобразовался к float (тут идёт неявное преобразование), и затем поделился на 255, таким образом мы ограничили значение цвета в диапазоне [0.0f; 1.0f] (вроде как можно применить термин нормализация, раз это вектор). Затем мы присваиваем полученные значения вектору pMem->environmentColorVec0, который уже там выровнен должным образом и всё такое.

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

Этот кусок удобно разделить на две части: разбиение одного dword на четыре dword и преобразование четырёх dword в четыре float (ну как я уже сказал альфы в данном случае нет, но в целом мы работаем с 4 компонентами). В описании к SSE я нашёл полезную инструкцию cvtdq2ps -- конвертирует 4x dword в 4x float (также есть и обратная cvtps2dq если чо). Поэтому вторую часть алгоритма я заассемблировал так:
Код:

asm( "movaps  xmm6, %1  \n\t"       
    "movaps  xmm0, %2  \n\t"
    "cvtdq2ps xmm0, xmm0 \n\t"
    "divps    xmm0, xmm6 \n\t"
    "movaps  %0,  xmm0 "

    : "=m"( pMem->environmentColorVec0 )
    : "m"( pMem->power ),
      "m"( pMem->swap ) );

В xmm6 сразу помещаем вектор из 255, достаточно один раз если не будете затирать регистр. Затем конвертируем, нормализуем и сохраняем в память. Этот участок кода однозначно работает быстрее -- я проверил.

Небольшое отступление: вот кстати есть movaps для выровненных данных, есть movups для невыровненных, и есть допустим addps у которой второй аргумент может быть прочитан из памяти, но не указано выровнен он или нет. Сразу возникает вопрос как лучше?: сначала загрузить через movaps и затем складывать или сразу пользоваться addps? (Видимо нужно смотреть мануалы к процессорам -- там должно быть написано сколько циклов занимают те или иные инструкции на разных процессорах...)

С первой же частью сложнее -- сдвиги я выполнял на регистрах общего назначения (РОН) и как мне кажется получился оверхед:
Код:

asm( "mov      eax,  %3  \n\t"
    "xor      ebx,  ebx  \n\t"
    "mov      bl,  al  \n\t"
    "mov      %0,  ebx  \n\t"
    "shr      eax,  8    \n\t"
    "mov      bl,  al  \n\t"
    "mov      %1,  ebx  \n\t"
    "shr      eax,  8    \n\t"
    "mov      bl,  al  \n\t"
    "mov      %2,  ebx  "

    : "=m"( pMem->swap[ 2 ] ),
      "=m"( pMem->swap[ 1 ] ),
      "=m"( pMem->swap[ 0 ] )
    : "r"( texEnvironmentColor )
    : "eax", "ebx" );

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

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

Ещё есть некоторые соображения насчёт вставки ассемблера в код С/С++. В GCC используется так называемый Extended Asm, крайне неудобная и запутанная вещь. НО, как мне кажется это следствие, а не причина, потому что причина в самом факте что нужно вставлять код ассемблера в код высокоуровневого языка. Компилятор не знает что внутри вставки, а программист пишущий вставку не знает как компилятор будет компилировать код. Предугадать состояние регистрового контекста до вхождения и восстановить его при выходе очень сложно. Если включается отпимизация то практически нереально. К тому же есть всякие ограничения, например на число параметров инлайн вставки. Ящитаю что выходом из этой ситуации будет раздельная компиляция -- С++ код в своём компиляторе, ассемблер в своём (fasm или что-то подобное), затем это вместе слинковывается. В данном случае логично будет оформить асмокод ввиде функции, а в соглашении вызовов есть чёткие правила о инициализации регистров, настройке стека, "сборки мусора" при возвращении из функции и т.д. что предотвратит всякие неожиданности со стороны компилятора. К тому же писание в отдельном файле будет стимулировать создавать большие куски асмокода что минимизирует оверхед на сам вызов этой функции, и кстати наличие большого количества ёмких регистров (даже в относительно старых процессорах) даёт возможность писать по нескольку страниц кода без обращения к памяти. Ну и просто приятный синтаксис с подсветкой в IDE/редакторах созданных специально для ассемблера играет важную роль, ведь от психического состояния программиста зависит конечный результат, насколько код будет качественный.

impersonalis 18.02.2015 23:35

Ответ: dword to float4 и обратно
 
чо за фигня со шрифтом?

Samodelkin 18.02.2015 23:38

Ответ: dword to float4 и обратно
 
Цитата:

Сообщение от impersonalis (Сообщение 293340)
чо за фигня со шрифтом?

Что именно? Некорректно отображатеся или просто не нравится?
Я поставил [font="Comic Sans MS"][color=#303030], так вроде для глаз лучше не? Просто тут такие скучные шрифты...

Phantom 19.02.2015 01:07

Ответ: dword to float4 и обратно
 
Samodelkin, http://lurkmore.to/Comic_Sans

mr.DIMAS 19.02.2015 01:38

Ответ: dword to float4 и обратно
 
2Samodelkin тебе с таким дрочерством надо идти в эмбеддеры - писать прошивки для микропроцессоров, но это так, к слову.

С SSE лучше\удобнее работать на интринсиках, и компилятор заодно оптимизирует SSE код.

Кстати, ты так и не пользуешься оптимизацией компилятора? Ну там может -O3 -msse2 поставить и сравнить скорости велика и то что компилятор сделает?

Samodelkin 19.02.2015 02:53

Ответ: dword to float4 и обратно
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293346)
2Samodelkin тебе с таким дрочерством надо идти в эмбеддеры - писать прошивки для микропроцессоров, но это так, к слову.

С SSE лучше\удобнее работать на интринсиках, и компилятор заодно оптимизирует SSE код.

Кстати, ты так и не пользуешься оптимизацией компилятора? Ну там может -O3 -msse2 поставить и сравнить скорости велика и то что компилятор сделает?

Не всё так плохо как может показаться -- у меня ассемблер только в двух функциях на несколько страниц кода. Эти функции являются софтварным аналогом пиксельных шейдеров. Если я их сделаю быстрыми -- вся программа станет быстрой. Это вот самый боттлнек, поэтому эти две функции стоят того чтобы над ними поработать. Больше нигде ассемблера нет.

Конечно пользоваться интринсиками или писать высокоуровнево удобней. Для какого-нибудь среднеуровневого игрового кода так и надо делать. Но критические места стоят затраченных усилий -- главное правильно сопоставить профит и затраты.

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

Оптимизация обфусцирует код. Очень сложно становится отлаживать что-то на уровне ассемблера, и как было показано в презенташке по DOD, компилятор может оптимизировать только 10% кода -- остальные 90% нужно делать программисту. Пока некоторые части моего велосипеда проигрывают, некоторые лучше чем отпимизированный код компилятора, но дело обстоит так исключительно из-за моих недоработок и какого-то незнания ассемблера. Это не финальная версия и я её буду улучшать. Ещё раз повторю это буквально 10-20 страниц на всю программу (где около 10к строк). Так что это никак не задрочество.

Со шрифтами не знал, сорри, попробую подобрать другие =).

mr.DIMAS 19.02.2015 14:06

Ответ: dword to float4 и обратно
 
Цитата:

Очень сложно становится отлаживать что-то на уровне ассемблера,
Отлаживают Debug-билд( -O0 ). А Release-билд( -O3 -msse2 ... ) просто компилят и кидают пользователю. Уж не думаешь ли ты что компилятор поломает твою программу? :-D

Samodelkin 19.02.2015 16:03

Ответ: dword to float4 и обратно
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293354)
Отлаживают Debug-билд( -O0 ). А Release-билд( -O3 -msse2 ... ) просто компилят и кидают пользователю. Уж не думаешь ли ты что компилятор поломает твою программу? :-D

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

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

mr.DIMAS 19.02.2015 16:52

Ответ: dword to float4 и обратно
 
А всякие сторонние библиотеки ты тоже собираешь без оптимизации, ну например булет?

Samodelkin 19.02.2015 17:11

Ответ: dword to float4 и обратно
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293356)
А всякие сторонние библиотеки ты тоже собираешь без оптимизации, ну например булет?

Обычно если предлагают скачать бинарный код то я качаю его, потому что он как минимум оттестирован. Если предлагают собирать самим, то предполагается что ты его тестировать будешь сам, потому что и компилятор и его настройки могут быть другими. Вариант с открытыми кодами хорош если ты собираешься модифицировать исходный код или глубоко интегрировать в свой проект. Если ты пользуешься чем-то как отдельной библиотекой то лучше качать бинарные коды.

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

А вот например тот же dx9 -- ты можешь посчитать хеш-суммы их дллок за последние 5 лет -- они все одинаковые, существует только один вариант бинарников, которые хорошо оттестирован.

mr.DIMAS 19.02.2015 17:14

Ответ: dword to float4 и обратно
 
Цитата:

Буллет я собирал без оптимизации
Без оптимизации он медленнее в 3-5 раз.

И вообще всё это недоверие больше походит на паранойю

Samodelkin 19.02.2015 17:26

Ответ: dword to float4 и обратно
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293358)
Без оптимизации он медленнее в 3-5 раз.

И вообще всё это недоверие больше походит на паранойю

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

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

mr.DIMAS 19.02.2015 17:32

Ответ: dword to float4 и обратно
 
Цитата:

я говорю что нужно проверять его работу
Не нужно. Ты же не пишешь код для медицинского оборудования, или для оборонки? Зачем тогда себе мозги лишний раз ебать?

Samodelkin 19.02.2015 17:39

Ответ: dword to float4 и обратно
 

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

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

mr.DIMAS 19.02.2015 17:47

Ответ: dword to float4 и обратно
 
Стрелки не нужно переводить. Я хочу услышать обоснованный ответ, зачем смотреть то что там компилятор наворотил? Наверное: "потому, что я могу" или "потому, что я хочу"

Samodelkin 19.02.2015 17:54

Ответ: dword to float4 и обратно
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293362)
Стрелки не нужно переводить. Я хочу услышать обоснованный ответ, зачем смотреть то что там компилятор наворотил? Наверное: "потому, что я могу" или "потому, что я хочу"

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

mr.DIMAS 19.02.2015 18:01

Ответ: dword to float4 и обратно
 
Соберу без оптимизации, найду баг, уберу его, запилю опять с оптимизацией. Если говорить про мою игру, то без оптимизатора она работает в 6 раз медленнее( 20 фпс против 120 )

Samodelkin 19.02.2015 18:28

Ответ: dword to float4 и обратно
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293365)
Соберу без оптимизации, найду баг, уберу его, запилю опять с оптимизацией. Если говорить про мою игру, то без оптимизатора она работает в 6 раз медленнее( 20 фпс против 120 )

Так падать то будет не у тебя, а у пользователя, который тебе дампы сунет и скажет давай исправляй.
Кстати во многих случаях я вообще без отладки обхожусь, то есть чтобы меня правильно понимали: 99% ошибок можно исправить из высокоуровневого языка и это даже продуктивней чем пошагово что-то отлаживать или тем более ассемблировать. Но это не значит что нужно полностью исключать такую возможность. В 1% потребуется основательная отладка: я уже (вроде даже тебе) рассказывал про Betrayer -- там глюк с видеодрайверами который не могут исправить почти год пруфлинк, просто потому что для них UE3 это чёрный ящик, из-за этого у них огромные проблемы со всей их затеей с этой игрой. При этом 10 лет опыта в индустрии. Вот как так можно? Понадеялись на UE3?
Я лучше заранее к таким ситуациям буду готов. Это кстати также касается того что я всегда рекомендую либо писать свой движок либо хорошенько разбирать устройство чужого движка, поначалу кажется что очень непродуктивно, нету быстрых прототипов и всё такое, зато много времени экономится в конце, когда код полностью котролируется, баги быстро правятся и вообще у всех хорошее настроение :)

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

Кстати работая над гбуфером ты использовал совсем другую философию, прям за каждый байт воевал, у шейдеров же тоже есть оптимизация. Можно было бы и незаморачиваться, само бы как нибудь заоптимизировалось. Ещё кто там кол-во инструкций считал чтобы глубину побыстрее восстановить. А кстати есть же ещё clang там куда более продвинутые оптимизаторы, вот его тебе надо ставить обязательно.

mr.DIMAS 19.02.2015 18:49

Ответ: dword to float4 и обратно
 
ох лол, плохой код... а ниче что я использую 4 сторонних библиотеки( из которых в рантайме только булет ) в которых и просядает вся производительность без оптимизации? я ж выше писал что булет тормозное говно без оптимизации, профайлер ставит мой код в конце списка потенциально медленных мест. кароч, твои аргументы шаткие и нет оснований тратить время, когда можно поменять ключ компилятора и получить профит здесь и сейчас и не ебать себе и окружающим мозги.

Samodelkin 19.02.2015 19:00

Ответ: dword to float4 и обратно
 
Я ещё раз говорю что я не отказываюсь от оптимизации, я ей пользуюсь как любым другим инструментом.
Мои аргументы вполне понятно расписаны, где, зачем и когда надо отключать оптимизацию.
С вашей стороны единственный аргумент это халява, а компилятор сам всё сделает, так что даже проверять результат нет причины.
Зачем тогда кодить на С++? Mr_F_ уже давно на юнити и шарпе.

mr.DIMAS 19.02.2015 19:16

Ответ: dword to float4 и обратно
 
Кто как хочет так и дрочит.


Часовой пояс GMT +4, время: 11:36.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot