win32 под vs2005 и быстродействие

BOPOH

Постоянный пользователь
Динозавры
Пользователь
9 Фев 2005
1.272
2
38
43
в 13000 км под Австралией
После нескольких лет юзания преимущественно явы, и писания на сях только под весьма специфические оси, возникла тут необходимость варганения win32 аппликухи. Под рукой оказалась 2005 студия - ей и воспользовался...

И тут я понял, что чего-то в этой жизни не понимаю...
В ней (2005-й студии), при разработке без всякого дотнета, C++ остался тем же?

Во-первых, я всю жисть считал, что сишные вычисления во флотах должны работать быстрее, чем в даблах. Хрен! Замена флотов на даблы быстродействие только повышает, причем, ОЧЕНЬ сильно (правда, все равно слабее, чем хотелось бы). Какого?

Во-вторых, что за хренотень творится с плавающеточечными функциями из math.h? Почему они работают с такой нереально черепашьей скоростью, что явовские вычисления той же сложности получаются в десятки, если не в сотни (!) раз быстрее?

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

То, как работает sqrt (а тем более - sqrtf), меня вообще убивает и наводит на мысли о создании таблицы корней.


А теперь объясните мне: че за хрень?? :blink:
Это я так привык к яве, что что-то сильно забыл в плюсах? Что именно?
Какая-то специфика компиляции именно под винду?
Или это в 2005-й студии все так заточено под дотнет, что без него уже и не работает толком. Ставить 6-ю?
 
Последнее редактирование модератором:

Liu

Пользователь
Пользователь
9 Фев 2005
743
0
0
И тут я понял, что чего-то в этой жизни не понимаю...
В ней (2005-й студии), при разработке без всякого дотнета, C++ остался тем же?
С какой точки зрения? Стандарт С++ не менялся, почему С++ в VS2005 должен быть другим?

Во-первых, я всю жисть считал, что сишные вычисления во флотах должны работать быстрее, чем в даблах. Хрен! Замена флотов на даблы быстродействие только повышает, причем, ОЧЕНЬ сильно (правда, все равно слабее, чем хотелось бы). Какого?
Мне тоже инетесно - почему ты так считал? Я вот считаю, что скорость вычислений с плавающей точкой зависит от матеметического сопроцессора.

Во-вторых, что за хренотень творится с плавающеточечными функциями из math.h? Почему они работают с такой нереально черепашьей скоростью, что явовские вычисления той же сложности получаются в десятки, если не в сотни (!) раз быстрее?
Смело заявление. Или сравнивается что-то разное, или что-то криво написано.

abs, который должен, по идее, выставлять один бит, работает так, буд-то шахматные задачи перебором решает. Простая пооверка знака с его заменой работает быстрее этого abs'а просто в несметное число раз.
Посмотрел исходник в VS2005:
int __cdecl abs (
int number
)
{
return( number>=0 ? number : -number );
}
Без комментариев.

То, как работает sqrt (а тем более - sqrtf), меня вообще убивает и наводит на мысли о создании таблицы корней.
Таблицы по любому быстрее.

А теперь объясните мне: че за хрень?? :blink:
Где хрень?

Это я так привык к яве, что что-то сильно забыл в плюсах? Что именно?
А что знал? :smile:

Какая-то специфика компиляции именно под винду?
Особенности компиляции под винду заканчиваются особенностями внутреннего устройства бинарников.

Или это в 2005-й студии все так заточено под дотнет, что без него уже и не работает толком.
Казало бы, причём тут .Net... :smile:

Я не против.
 

metod

Пользователь
Пользователь
12 Фев 2005
264
0
0
42
наверное перед "расхваливанием" студии хорошо бы было б посмотреть на исходники...
 

BOPOH

Постоянный пользователь
Динозавры
Пользователь
9 Фев 2005
1.272
2
38
43
в 13000 км под Австралией
С какой точки зрения? Стандарт С++ не менялся, почему С++ в VS2005 должен быть другим?
По моим представлениям, не должен - потому и спрашиваю.


Мне тоже инетесно - почему ты так считал? Я вот считаю, что скорость вычислений с плавающей точкой зависит от матеметического сопроцессора.
Т.е. бывают типы сопроцессора, на которых вычисления с 8-байтовыми числами производятся быстрее, чем с 4-байтовыми? Че-то мне сомнительно.
Раньше я такую фигню встречал только в той же самой яве, но там все объяснялось просто - jvm по определению работает с даблами, а флоты при вычислении в них переводит. В сях такого, по-моему, быть не должно. При любом сопроцессоре.


Смело заявление. Или сравнивается что-то разное, или что-то криво написано.
Много ли разного можно сравнивать в представлени геометрических расчетов? Строго говоря, текст в одном и другом языках отличается только заменами вроде sqrt вместо Math.sqrt.


Посмотрел исходник в VS2005:
Без комментариев.
Ну, тогда моя не понимать, почему замена вызова abs'а на ту же самую строчку, что содержится в нем, дает такой прирост производительности. Только засчет сокращения времени как такового вызова функции? И чтобы это давало выигрыш в 15-20 мс на каждые 15-20 млн вызовов?


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


Да вот там же, как говорится, и ссуть :smile:

Что-то знал, вроде. Как минимум, хеллоу ворлд

Казало бы, причём тут .Net... :smile:
Да я уже не знаю, что тут причем может быть. Но что-то же должно :smile: Под другими осями я таких глюков не наблюдал, а под виндами других компилеров не пробовал - вот и интересно, кто виноват.
 

BOPOH

Постоянный пользователь
Динозавры
Пользователь
9 Фев 2005
1.272
2
38
43
в 13000 км под Австралией
наверное перед "расхваливанием" студии хорошо бы было б посмотреть на исходники...
Исходники на работе, так что дословно щас не воспроизведу, но ничего особо хитрого. Сам проект-то здоровый, но критичная часть - вычисления на уровне float a = k*k/sqrtf(1-b*b);
 

Liu

Пользователь
Пользователь
9 Фев 2005
743
0
0
По моим представлениям, не должен - потому и спрашиваю.
Обычный C++. IMHO, наиболее полно соотвествующий стандарту на момент выхода. Как сейчас - не скажу.

Т.е. бывают типы сопроцессора, на которых вычисления с 8-байтовыми числами производятся быстрее, чем с 4-байтовыми? Че-то мне сомнительно.
Раньше я такую фигню встречал только в той же самой яве, но там все объяснялось просто - jvm по определению работает с даблами, а флоты при вычислении в них переводит. В сях такого, по-моему, быть не должно. При любом сопроцессоре.
У тебя же не возникает вопросов почему работать с INT (4 байта) быстрее, чем с SHORT (2 байта). Могу путать, но разрядномть математических сопроцессоров сейчас где-то на уровне 80 бит...

Много ли разного можно сравнивать в представлени геометрических расчетов? Строго говоря, текст в одном и другом языках отличается только заменами вроде sqrt вместо Math.sqrt.
Это как написать...

Ну, тогда моя не понимать, почему замена вызова abs'а на ту же самую строчку, что содержится в нем, дает такой прирост производительности. Только засчет сокращения времени как такового вызова функции? И чтобы это давало выигрыш в 15-20 мс на каждые 15-20 млн вызовов?
Не знаю чем замерял, но 16 мсек - это погрешность таймера в винде (я про GetTickCount).

С этим не спорю, но вот почему явовский расчет намного быстрее работает, я этого понять не могу. Там же не на таблицах построено, а вызовов полюбому должно больше быть.
Как уже выше написано - надо знать что сравнивается. Я не настолько хорошо знаю Java, что бы сказать почему там так.

Да вот там же, как говорится, и ссуть :smile:
IMHO, до сути ещё далеко. :wink:

Что-то знал, вроде. Как минимум, хеллоу ворлд
Хороший минимум, жаль, что не кандидатский. :smile:

Да я уже не знаю, что тут причем может быть. Но что-то же должно :smile: Под другими осями я таких глюков не наблюдал, а под виндами других компилеров не пробовал - вот и интересно, кто виноват.
С чем сраниваем под другими осями?
 

BOPOH

Постоянный пользователь
Динозавры
Пользователь
9 Фев 2005
1.272
2
38
43
в 13000 км под Австралией
Это как написать...
Ну, дословно, по вышеозвученной причине, сейчас не воспроизведу. Насколько я себе представляю, межтиповых преобразований - минимум. Внутритиповые.. ммм.. ну, кроме все той же замены абса, места объявления временных переменных или записи чисел в стиле "1.0f" вместо "1" ничего, хоть в какой-то мере влияющего на быстродействие, быть не должно.


Не знаю чем замерял, но 16 мсек - это погрешность таймера в винде (я про GetTickCount).
В моем случае - это 1-2 пропущенных кадра видео при частоте 73 fps, так что замеряется достаточно строго.


Хороший минимум, жаль, что не кандидатский. :smile:
Кандидатский, к счастью, сдал год назад :smile:

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

firetrap

Активный пользователь
Пользователь
9 Фев 2005
988
11
18
хватит флудить попусту, код в студию! (ява, сипп)..

ЗЫ. развели тут демагогию :biggrin:

ЗЗЫ. Не будет кода - не будет темы :biggrin:
 

metod

Пользователь
Пользователь
12 Фев 2005
264
0
0
42
Ворон все-таки продемонстрируй вот этот кусочек кода на яве и на VC, с использованием счетчика времени. а потом действительно по существу будет разговор. К сожалению видимо Яву только ты хорошо знаешь...
 

Liu

Пользователь
Пользователь
9 Фев 2005
743
0
0
Ну, дословно, по вышеозвученной причине, сейчас не воспроизведу. Насколько я себе представляю, межтиповых преобразований - минимум. Внутритиповые.. ммм.. ну, кроме все той же замены абса, места объявления временных переменных или записи чисел в стиле "1.0f" вместо "1" ничего, хоть в какой-то мере влияющего на быстродействие, быть не должно.
Если честно, то не очень понимаю, что ты подразумеваешь под "внутретиповыми преобразованиями". А на быстродействие много чего влиять может - для этого профайлеры и придумали. :wink:

В моем случае - это 1-2 пропущенных кадра видео при частоте 73 fps, так что замеряется достаточно строго.
Тут я не в теме....

Кандидатский, к счастью, сдал год назад :smile:
Поздравляю, но видимо он был не по программированию. :smile:

Под другими осями программы были другие, но тоже в основном вычислительные. Из того делаю вывод, что если бы проблема была в понимании стандарта языка - наверное, я бы столкнулся с ней раньше.
Ну, тогда сравнивать безполезно - код должен быть одинаковым. Да и, я что-то не припомню тестов где бы была зависимость математических вычислений от ОС...
 

NICE

Пользователь
Пользователь
9 Фев 2005
389
0
0
37
Хм На самом деле всё довольно просто узнать. Нужно написать 2 проги на яве и идеинтичную на с++ в торой будут бонально только эти функции abs итд.а потом с помощю дизассемблера сравнить два листинга и коды генерируемые компиляторами.Я тоже считаю что такого большого отставания не должно быть ибо байт код впринцепи должен быть одинаков
+- пару тактов.Так же испробывать оптимизацию по скорости итд хотя я думаю на выполнение мат операций она особо не повлияет тк оптемизация выполняется с развёртыванием циклов итд(Тоесть не особо критичные изменения).
Вот и провести тестирование !)) А результаты вылажить на ворум )
 

metod

Пользователь
Пользователь
12 Фев 2005
264
0
0
42
Хм На самом деле всё довольно просто узнать. Нужно написать 2 проги на яве и идеинтичную на с++ в торой будут бонально только эти функции abs итд.а потом с помощю дизассемблера сравнить два листинга и коды генерируемые компиляторами.Я тоже считаю что такого большого отставания не должно быть ибо байт код впринцепи должен быть одинаков
+- пару тактов.Так же испробывать оптимизацию по скорости итд хотя я думаю на выполнение мат операций она особо не повлияет тк оптемизация выполняется с развёртыванием циклов итд(Тоесть не особо критичные изменения).
Вот и провести тестирование !)) А результаты вылажить на ворум )
хм, разве яву можно дизассемблить? хм
 

BOPOH

Постоянный пользователь
Динозавры
Пользователь
9 Фев 2005
1.272
2
38
43
в 13000 км под Австралией
Ворон все-таки продемонстрируй вот этот кусочек кода на яве и на VC, с использованием счетчика времени.
Ок, в понедельник выложу, как до работы доберусь.

хм, разве яву можно дизассемблить? хм
Именно "дизассемблировать" нельзя. Есть всякие извратные "трансляторы" в асм, но то, что они генерят, вовсе не обязано прямо отражать команды, получаемые процессором, когда программу явамашина выполняет.
 

metod

Пользователь
Пользователь
12 Фев 2005
264
0
0
42
Ок, в понедельник выложу, как до работы доберусь.


Именно "дизассемблировать" нельзя. Есть всякие извратные "трансляторы" в асм, но то, что они генерят, вовсе не обязано прямо отражать команды, получаемые процессором, когда программу явамашина выполняет.
Я именно это и имел в виду, Ява не создает exe.
 

BOPOH

Постоянный пользователь
Динозавры
Пользователь
9 Фев 2005
1.272
2
38
43
в 13000 км под Австралией
Тек-с, конкретизируем разговор. Если мне кто расскажет, где я тут принципиально напортачил - буду премного благодарен.

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

Вначале идут некоторые определения, потом, между двух замеров времени - сами вычисления.

Итак, явовский вариант:

static final int IMG_WIDTH = 1024;
static final int IMG_HEIGHT = 768;
static final int IMG_WIDTH2 = IMG_WIDTH/2;
static final int IMG_HEIGH2 = IMG_HEIGHT/2;
static final long RASTER_SIZE = IMG_WIDTH * IMG_HEIGHT * 3;

int r = jSlider1.getValue();

long startMS = System.currentTimeMillis();
for (int x = 0; x < IMG_WIDTH; x++)
for (int y = 0; y < IMG_HEIGHT; y++) {
long ind1 = RASTER_SIZE - ((y+1)*IMG_WIDTH - x)*3;
int xp = x - IMG_WIDTH2;
int yp = IMG_HEIGH2 - y;
if (yp > 0) {
double k = xp / yp;
k = Math.abs(k);
}
double Ca2 = xp*xp + yp*yp;
double Ca = Math.sqrt(Ca2);
double shift = Ca*(1 - r/Math.sqrt(r*r - Ca2));
}
long workTime = System.currentTimeMillis() - startMS;

workTime получается в диапазоне 172-188.

Теперь вариант сишный, как я его написал навскидку:

const static int IMG_WIDTH = 1024;
const static int IMG_HEIGHT = 768;
const static int IMG_WIDTH2 = IMG_WIDTH/2;
const static int IMG_HEIGH2 = IMG_HEIGHT/2;
const static long RASTER_SIZE = IMG_WIDTH * IMG_HEIGHT * 3;

int r = Settings.m_StreightRadius;

DWORD startMs = GetTickCount();
for (int x = 0; x < IMG_WIDTH; x++)
for (int y = 0; y < IMG_HEIGHT; y++)
{
long ind1 = RASTER_SIZE - ((y+1)*IMG_WIDTH - x)*3;
int xp = x - IMG_WIDTH2;
int yp = IMG_HEIGH2 - y;
if (yp > 0)
{
double k = (double) xp / yp;
k = abs(k);
}
double Ca2 = xp*xp + yp*yp;
double Ca = sqrt(Ca2);
double shift = Ca*(1.0 - r/sqrt(r*r - Ca2));
}
DWORD workTime = GetTickCount() - startMs;

Здесь workTime получается 250-265.
Заметно медленнее явовского варианта.

Теперь то, что я говорил про абс. Заменяем строчку с ним на

k = k < 0 ? -k : k;

workTime сразу падает до 203-219.
Весьма существенно, я бы сказал, быстрее стало. Но все равно медленнее, чем на яве! Причем, на явовский вариант аналогичная замена вообще не влияет.

Теперь пробуем заменить даблы на флоты:

float k = (float) xp / yp;
float Ca2 = xp*xp + yp*yp;
float Ca = sqrtf(Ca2);
float shift = Ca*(1.0f - r/sqrtf(r*r - Ca2));

В результате, workTime получается 297-312.
Для меня такое падение скорости странно, но насколько я понял Liu - эффект почти ожидаемый. Для явы таковое падение тоже имеет место быть, но в ней все объяснимо строго.

Ну, и для полноты картины, пробуем снова воспользоваться абсом, теперь со флотами:

k = abs(k);

workTime скачет до 343-360.


Итого, сишный вариант результата явовского достичь не смог. Вопрос: почему?


З.Ы. По ходу дела побочный вопрос, прямого отношения к теме не имеющий: в студии можно где-нибудь посмотреть stdout в процессе дебажного запуска? А то отдельно запускать для этого экзешник не шибко удобно...

З.З.Ы. Блин, как этому дурацкому форуму пробелы-то вставить в начале строк..
 
Последнее редактирование модератором:

Liu

Пользователь
Пользователь
9 Фев 2005
743
0
0
Если не секрет, конечно, то как ты эти цифры получил?
Дело в том, что в релизе этот цикл просто выкидывается...
 

metod

Пользователь
Пользователь
12 Фев 2005
264
0
0
42
незнаю, может бред конечно, но я прогнал это цикл несколько раз, в результате пишет, что время исполнения равно 0. Цикл работает 100%. поставил еще Sleep("задержка"), время выполнения проги становится равной задержке.
 

Liu

Пользователь
Пользователь
9 Фев 2005
743
0
0
незнаю, может бред конечно, но я прогнал это цикл несколько раз, в результате пишет, что время исполнения равно 0. Цикл работает 100%. поставил еще Sleep("задержка"), время выполнения проги становится равной задержке.
Конечно... Потому VS эти циклы выкидывает с целью оптимизации. %)