Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Glоbus, Вы писали:
G>>Думается мне, что товарищ Дворкин таки прав насчет оптимизации и стремлении к ней как к недостижимому идеалу коммунизьма. Умение писать быстрые проги с минимальными требованиями по памяти — это в некотором смысле культура пргграмминга.
IT>Это ты про ассемблер что-ли?
Это вообще ... за жисть... Слысл таков, что если программер как одно из основных правил возьмет себе постоянно думать о том, как бы сделать текущий кусок кода оптимальным и стремится к этому т осо временем у человека просто вырабоатется другой подход — он с первого раза будет реализовывать 90% тех оптимизационных фич, о которых обычно вспоминают потом. Самый банальный пример — передача в плюсах объектов в функцию по ссылке а не по значению — тот же например std::string. В подавляющем большенстве случаев параметры функций используются именно как read-only и такой подход уже приведет к небольшому, но ускорению и экономии по памяти. И таких маленьких тонкостей в тех же плюсах может быть бесконечное множество. Так вот нужно чтоб чел воспитал в себе вот это умение "видеть". Говоря философски , в самой природе человека должно быть заложенро стремление сделать лучше сильнее быстрее, тогда он будет сам учится, развиваться и в конце концов поднимать свой уровень, что позволит писать ему эффективный код.
Здравствуйте, eao197, Вы писали:
E>А что, кто-то точно знает, что такое "ОО-анализ"?
Вот лично я не знаю, что такое обычный ОО-анализ, хотя именно этот самый анализ и является сферой моих профессиональных интересов и обязанностей. Методик этого самого анализа море (а кое кто вобще без них обходится, причем успешно), но ни одной общепризнанной.
Здравствуйте, VladD2, Вы писали:
VD>С тех времен прошло уже 12 лет (если не ошибаюсь). И мне казалось что уже все знают, что посимвольное чтение из файла — это совершенно не смертельно. Но вот появляется еще один перформанс-варьер который не был столь прозорлив чтобы наступить на эти грабли 12 лет назад, и делает смелые заявления
Хочу возразить и жестко. Буквально год назад я столкнулся с тем, что на VB девушка программист выданный ей массив байтов записывала в файл побайтово. Так вот, когда этот код на VB заменили на запись всего массива за раз, то скорость выросла примерно на два порядка. Я понимаю, что это особенности VB, но тем не менее, все грешили на то, что тормозит Сишный код, который формировал этот массив байтов.
Так что не всегда посимвольная в данном случае запись является не смертельной.
Здравствуйте, eao197, Вы писали:
E>Таких POD типов не так уж мало. Два поля типа int в C-шной структуре и все -- POD тип в два раза больше указателя получается.
Кстати, такой объект есть в Win32 — POINT, 8 байт. И в Win32 есть функции, которые принимают его по значению. Причина — в Win16 POINT имел размер в 4 байта, указатель на него (дальний) — тоже 4 байта, так что все равно. А изменить интерфейс функции Win API, естественно, нельзя.
У меня буквально на днях на занятии было вот что. Показывает мне студент код (реально он его из Петцольда выдрал, я им не запрещаю, лишь бы разобрались — технические приемы). И вот у него (т.е у Петцольда) там POINT передается по значению. А функция, к слову сказать, вызывается на сообщении WM_MOUSEMOVE, так что чаще чем десятки раз в секунду ее все равно не вызовешь. И делается там много такого (рисование линий в режиме R2_NOT), что на фоне этого оверхед в 4 байта — форменный пустяк. Ни на быстродействие, ни на память это не влияет.
Должен был я ему замечание сделать или нет ?
Я замечание сделал. Аргумент простой — если он привыкнет передавать объекты с размером больше sizeof(void*) по значению — будет это и дальше делать, причем там, где это может серьезно сказаться.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Должен был я ему замечание сделать или нет ?
PD>Я замечание сделал. Аргумент простой — если он привыкнет передавать объекты с размером больше sizeof(void*) по значению — будет это и дальше делать, причем там, где это может серьезно сказаться.
+1
Я и сам такие замечания делаю. Если с "детства" приучить С++ программиста передавать пользовательские типы по константным ссылкам или указателям, то проблем с производительностью на ровном месте у него точно не будет. И если нужно будет устранить какой-нибудь bottle neck, то изменять придется либо архитектурное решение, либо алгоритм. А не банальную передачу std::string по значению.
писал, что благодоря языку C++ на сложной вычислительно задаче и слабой технике у нас не было проблем с производительностью. Вообще. Потому, что мы не теряли ее на элементарных операциях -- т.к. передача аргументов в функции или обращения к элементам массива.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
писал, что благодоря языку C++ на сложной вычислительно задаче и слабой технике у нас не было проблем с производительностью. Вообще. Потому, что мы не теряли ее на элементарных операциях -- т.к. передача аргументов в функции или обращения к элементам массива.
Именно. Проще говоря, у вас сформирована была определенная культура написания кода, при котрой он пишется наиболее эффективным образом. При данном дизайне, данной архитектуре. И если потом проблемы возникнут — это может быть из-за неэффективного алгоритма, неправильной архитектуры или, может быть, из-за недооценки требований к железу (не тянет эта машина такое). А не из-за того, что кто-то съел 30% времени на бессмысленный вызов конструктора копирования и деструктора или насоздавал с десяток временных матриц.
Pavel Dvorkin wrote:
> Я замечание сделал. Аргумент простой — если он привыкнет передавать > объекты с размером больше sizeof(void*) по значению — будет это и > дальше делать, причем там, где это может серьезно сказаться.
Кстати о птичках. Мы тестировали что эффективнее передавать — ссылку на
CSize (те же 8 байт) или сам CSize по значению. Оказалось, что разницы
нет. Точнее, на одних процессорах (Intel Pentium M) был быстрее
указатель, а на других (AMD не-помню-какой) было выгодно передавать по
значению.
Здравствуйте, Cyberax, Вы писали:
C>Кстати о птичках. Мы тестировали что эффективнее передавать — ссылку на C>CSize (те же 8 байт) или сам CSize по значению. Оказалось, что разницы C>нет. Точнее, на одних процессорах (Intel Pentium M) был быстрее C>указатель, а на других (AMD не-помню-какой) было выгодно передавать по C>значению.
А CRect?
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, vdimas, Вы писали:
VD>>Очень часто ты вместо ответа на мои слова разговариваешь сам с собой. Например: VD>>
V>>>> Лично я поддержал сам факт обсуждения этой темы. Согласен, что Дворкин немного перегибает,
VD>>>Будем надеяться, что тройка поставленная им за твое сообщение в том числе включает и согласие с этим вот высказыванием.
VD>>Что означает моя оценка я уже обяснил. Поддержку и раскрытие самой темы. Оценки привлекают читателей, не правда ли?
VD>>Создается впечатлинеие, что ты сражашся с вымышленным противником.
V>Где-то я уже слышал это недавно...
V>Влад, если бы ты знал на какой уровень домысливания приходится настраиваться, читая твои посты... V>Я прекрасно знаю, что обсуждение очепяток оппонентов находится за правилами RSDN, но тут уже просто количество переходит в качество, в требование определенного настроя...
Здорово! То есть ты перечитал текст, понял что сморозил ерунду и вместо того чтобы сказать "извини, плохо прочел" решил перевести разговор на обсуждение моих опечаток? А не объяснишь ли ты чем в донном случае мои опечатки помешали тебе отличить смысл слов "им" и "тобой"?
V>Конкретно в приведенном примере, да, получается что я домыслил твое предложение неверно.
V>Тогда ответ на тот абзац мог бы быть примерно таким: V>"По-абзацное оценивание не предусмотрено, к сожалению..."
Причем тут пообзацное оценивание? Я выразил легкий сарказм по поводу того, что он поставил оценку за сообщение которое во многом противоречит его суждениям.
Так понятно?
ЗЫ
Вообще меня угнетает мысль о том, что необходимо разжевывать любую мысль, а такие вещи как сарказм и юмор вообще восринимаются не адекватно. Подозреваю, что конечно в этом виноват я.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, eugen1001, Вы писали:
E>Хочу возразить и жестко. Буквально год назад я столкнулся с тем, что на VB девушка программист выданный ей массив байтов записывала в файл побайтово. Так вот, когда этот код на VB заменили на запись всего массива за раз, то скорость выросла примерно на два порядка. Я понимаю, что это особенности VB, но тем не менее, все грешили на то, что тормозит Сишный код, который формировал этот массив байтов.
E>Так что не всегда посимвольная в данном случае запись является не смертельной.
И какой вывод? Варианты ответов:
1. Ни в коем случ не пишите в файл по одному байту.
2. Ищите места снижающие производительность и устраняйте их.
И еще вопрос. Предположим, чтобы утранить эту проблему можно:
1. Переписать алгоритм записи данных используя буфер.
2. Использовать кэшурующую оберкту для объекта проивзодящего запись в файл.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Должен был я ему замечание сделать или нет ?
PD>Я замечание сделал. Аргумент простой — если он привыкнет передавать объекты с размером больше sizeof(void*) по значению — будет это и дальше делать, причем там, где это может серьезно сказаться.
Например где?
Вот простейший пример:
#include <iostream>
#include <Windows.h>
#include <time.h>
#include <math.h>
//typedef POINT POINT_PARAM;typedef const POINT &POINT_PARAM;
void __declspec(noinline) normalize(POINT_PARAM vect, POINT* res)
{
double norm = sqrt(double(vect.x * vect.x + vect.y * vect.y)) / 100;
res->x = LONG(vect.x / norm);
res->y = LONG(vect.y / norm);
}
int main(void)
{
POINT vect = {30, 40};
POINT nv;
clock_t start = clock();
for (unsigned i = 0; i < 100000000; ++i)
normalize(vect, &nv);
clock_t time = clock() - start;
std::cout << time << std::endl;
return 0;
}
Функция normalize. Принимает POINT и возвращает его нормализованным.
Внимание, вопрос. Как это point будет эффективнее принимать? по ссылке или по значению?
Ответ (Pentium D 2.80, VC7.1 без оптимизации):
Время работы при передаче по ссылке: 10921
Время работы при передаче по значению: 10734 (на 2% меньше!)
Тому , чему надо . Ты не понял суть моего высказывания
>Аргумент простой — если он привыкнет передавать объекты с размером больше sizeof(void*) по значению — будет это и дальше делать, причем там, где это может серьезно сказаться.
Здесь не идет речь о POINT, с ним, вполне возможно, разницы нет. Я имел в виду, что и в других случаях они будут это делать, там где размеры могут доходить до десятков и сотен байтов + конструктор копирования. Если не привыкнут сразу думать о том, что они передают и во что это превращается в коде.
Здравствуйте, eao197, Вы писали:
C>>Кстати о птичках. Мы тестировали что эффективнее передавать — ссылку на C>>CSize (те же 8 байт) или сам CSize по значению. Оказалось, что разницы C>>нет. Точнее, на одних процессорах (Intel Pentium M) был быстрее C>>указатель, а на других (AMD не-помню-какой) было выгодно передавать по C>>значению. E>А CRect?
Не тестировали. У нас в одном модуле просто была задача быстро обработать несколько миллионов размеров, вот и искали оптимальный вариант. С CRect уже скорее всего будет эффективнее передача по ссылке.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, eugen1001, Вы писали:
E>>Хочу возразить и жестко. Буквально год назад я столкнулся с тем, что на VB девушка программист выданный ей массив байтов записывала в файл побайтово. Так вот, когда этот код на VB заменили на запись всего массива за раз, то скорость выросла примерно на два порядка. Я понимаю, что это особенности VB, но тем не менее, все грешили на то, что тормозит Сишный код, который формировал этот массив байтов.
E>>Так что не всегда посимвольная в данном случае запись является не смертельной.
VD>И какой вывод? Варианты ответов: VD>1. Ни в коем случ не пишите в файл по одному байту. VD>2. Ищите места снижающие производительность и устраняйте их.
VD>И еще вопрос. Предположим, чтобы утранить эту проблему можно: VD>1. Переписать алгоритм записи данных используя буфер. VD>2. Использовать кэшурующую оберкту для объекта проивзодящего запись в файл.
Выводов два:
1. В каждом отдельном случае нужно отдельно изучать ситуацию, по возможности точно контролировать в какой момент времени и почему тормозит.
В нашем случае показано, что бывают ситуации, когда работа по одному байту или блоками особой роли не играет, а бывает, когда очень даже играет.
2. Прежде, чем что-то оптимизировать, да еще с серьезными переделками, нужно провести оценку: соизмерим ли ожидаемый выйгрыш по времени с затратами на оптимизацию.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здесь не идет речь о POINT,
Здесь-то она может и не идет, а вот там где вы со студентом пинали Петцольда — шла именно о POINT-е.
И студент теперь будет всегда передавать по ссылке все типы, у которых размер > sizeof(void *).
PD>с ним, вполне возможно, разницы нет.
В том-то и дело, что в приведенном мною примере разница есть. Передача по значению оказалась эффективнее.
И таких примеров тысячи. В конце концов, sizeof(double) тоже > sizeof(void *), но вряд ли будет разумно и его везде по ссылке передавать. ТщательнЕЕ надо...
PD>Я имел в виду, что и в других случаях они будут это делать, там где размеры могут доходить до десятков и сотен байтов + конструктор копирования. Если не привыкнут сразу думать о том, что они передают и во что это превращается в коде.
+1
Здравствуйте, Cyberax, Вы писали:
E>>А CRect? C>Не тестировали. У нас в одном модуле просто была задача быстро обработать несколько миллионов размеров, вот и искали оптимальный вариант. С CRect уже скорее всего будет эффективнее передача по ссылке.
А я вот накатал тестик. Вот результаты под Visual C++ 7.1 (-GX, -O2):
), похоже, при локальных вычислениях компилятор аргументы может по регистрам рассовать и этим достичь преимущества. Но, все же, при передаче аргументов по ссылке много не проиграешь, это точно.
Код теста:
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
const unsigned int iterations = 10000000;
struct my_pod_2int_t
{
int m_x;
int m_y;
};
struct my_pod_3int_t
{
int m_x;
int m_y;
int m_cx;
};
struct my_pod_4int_t
{
int m_x;
int m_y;
int m_cx;
int m_cy;
};
struct my_pod_5int_t
{
int m_x;
int m_y;
int m_cx;
int m_cy;
int m_area;
};
struct my_byte_pod_t
{
char m_x;
char m_y;
char m_cx;
char m_cy;
};
template< class R, class T0, class T1, class T2, class T3 >
void
meter(
const std::string & test_case_name,
const std::string & method_name,
R (*pfn)( T1, T2, T3 ),
const T0 & a,
const T0 & b,
const T0 & c )
{
std::cout << test_case_name << "::" << method_name << " " << std::flush;
std::clock_t start = std::clock();
for( unsigned int i = 0; i != iterations; ++i )
(*pfn)( a, b, c );
std::clock_t finish = std::clock();
std::cout << "duration: "
<< double( finish - start ) / CLOCKS_PER_SEC
<< std::endl;
}
template< class TestCase >
void
initiate_meter( const std::string & test_case_name )
{
typename TestCase::value_t a, b, c;
meter( test_case_name, "references_only",
&TestCase::references_only, a, b, c );
meter( test_case_name, "refereces_args_value_return",
&TestCase::refereces_args_value_return, a, b, c );
meter( test_case_name, "all_values",
&TestCase::all_values, a, b, c );
}
template< class T >
class test_case_t
{
public :
typedef T value_t;
static const value_t &
references_only(
const value_t & a,
const value_t & b,
const value_t & c )
{
return a;
}
static value_t
refereces_args_value_return(
const value_t & a,
const value_t & b,
const value_t & c )
{
return a;
}
static value_t
all_values(
value_t a,
value_t b,
value_t c )
{
return a;
}
};
#define INITIATE_METER( type ) \
initiate_meter< test_case_t< type > >( #type )
int main()
{
INITIATE_METER( my_pod_2int_t );
INITIATE_METER( my_pod_3int_t );
INITIATE_METER( my_pod_4int_t );
INITIATE_METER( my_pod_5int_t );
INITIATE_METER( my_byte_pod_t );
}
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Тут ошибочка у вас Павел вышла. Сам недавно на такое наткнулся. В этом случае Петцольд был прав. Зря студент пострадал.
Начиная с Пентиумов шина 64 битная. То есть за раз, она забирает 8 байт. И не меньше. В результате если значение не в массиве, то разницы между 4 байтами и 8 байтами нет.
А ты знаешь? Можно подробней?
На отсутствие единого формального процесса я указал еще 2 поста назад (могу, кстати, подкинуть мысль, почему дело обстоит именно так, и заметь, не только в ОО-анализе). Однако, общая схема одинакова — анализ предметной области, построение оптимальной статической и динамической модели.
Мне казалось, что я выразился предельно ясно, а тебе, очевидно, поразвлекаться захотелось. Без достаточной проработки самой модели и всех ее уровней с функциональной т.з. и с т.з. всевозможных ограничений, бросаться в конкретику паттернов, ИМХО, рановато. Тем более, что сами паттерны GoF как раз относятся к статической части модели, на которую мы должны выходить в последнюю очередь (а не начинать с нее, исключения про библиотеки предназначенные для повторного применения обсуждать здесь не буду). Применение паттернов должно являться СЛЕДСТВИЕМ анализа (или, учитывая итеративность, можно уточнить так: следствием очередной итерации анализа), а не обогощать модель лишней/ненужной функциональностью, взятой с потолка или же заведомо рубить требования ввиду ограничений самих паттернов или применяемых связок паттернов. Можно много сказать об итеративности и возвратах в процессе анализа проектирования по мере уточнения и развития модели. Сами эти моменты крайне важны, т.к. очень часто решения раннего этапа проектирования могут вполне огранично подменяться на более поздних итерациях, зачастую упрощаться, "склеиваться", вычленяться похожие части и т.д.
А я лично наблюдал недавно процесс разработки примерно в таком духе: "Ну, тут мы прилепим это, здесь то, а вот в этом месте нечто эдакое, я тут новый ультрасовременный паттерн недавно в и-нете нарыл, очень хочу попользовать прямо здесь и сейчас". И потом вся система с большим трудом втискивается в это прокрустово ложе шапкозакидательских ничем не обоснованных решений. Буквально пару недель назад я помогал разруливать одну из (вполне ожидаемых) "сложностей", которая возникла, вот ведь незадача, уже на этапе воплощения продукта.
И вообще, если охота более конкретно порассуждать о тонкостях ОО-проектирования, ты не стесняйся, высказывайся, только уж пожалуйста, немного более предметно, ok? А то разговор с тобой какой-то односторонний получается. И что не вывод у тебя — так пальцем в небо (ты уж извини, но кому там что требовалось доказать, а главное зачем — я так и не понял ). Вероятнее всего, я кому-то на больной мозоль наступил. Если это так, то возьму свои слова обратно, если оппонент потрудится хотя бы намеком обосновать свою позицию или хотя бы обрисовать собственный интерес в этой ветке спора.
------------
Хотя, положа руку на сердце, я не отношусь к ОО-проектированию с тем религиозным трепетом, который наблюдал у некоторых оппонентов. Нет, здесь никого конкретно не имею ввиду, но на других ресурсах в форумах до смешного доходило. Мне, как электронщику-цифровику со стажем ОО-проектирование преставлется частным случаем того самого системного подхода, применяемого при разработке вычислительных систем/сетей, не более того. Да, есть свои тонкости и акценты, и цена ошибки не так высока (!!! имено ), но суть та же. И кстати, единой формальной методологии разработки вычислительных систем так же не существует. Неплохо формализован расчетный аппарат, но это опять же, лишь вспомогательный инструмент.
А по мне существует только один паттерн который называется Low Coupling/High Cohesion. Все остальное есть эквилибристика ума одного или нескольких индивидуумов в условиях границ функциональный и нефункциональных требований по достижению наибольшей близости к данному паттерну.