LINUX.ORG.RU

Кто там кукарекал про С++?


1

8

Задача: разработать кроссплатформенное клиент-серверное приложение под Windows/Linux на С++ (boost, ace, etc.), клиент построчно считывает с консольки введёные числа, отправляет на сервер, сервер в ответ плюёт разложением чисел на простые множители. Стандартное тестовое задание, ничего интересного.

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

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

class server
{
public:
  server(boost::asio::io_service& io_service, short port)
    : io_service_(io_service),
      acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
  {
    session* new_session = new session(io_service_);
    acceptor_.async_accept(new_session->socket(),
        boost::bind(&server::handle_accept, this, new_session,
          boost::asio::placeholders::error));
  }
  .......

Смеха ради, да и чтоб не вырвало от такого кода, накидал за полчаса решение на Haskell.
Что получилось:

  • Разбор параметров командной строки
  • Клиент-серверная архитектура
  • Полностью асинхронный многопоточный tcp-сервер
  • Поддержка unicode, IPv6 и BigInteger из коробки
  • Мемоизация (благодаря ленивости) из коробки
  • Полная кроссплатформенность (*nix, Mac OS, Windows etc.)
  • Правильность тривиально доказывается мат. индукцией по коду
  • Исходник чуть больше 60 строк (в 8 раз меньше, чем на крестах)

Если поднатужиться (я не стал) и заменить алгоритм нахождения простых чисел/простых множителей на более оптимальный, то ко всему прочему получаем автоматическую распараллелизацию алгоритмов из коробки (см. Data Parallel Haskell) и произодительность на уровне чистого Си/Фортрана.

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

★★★★★

Ответ на: комментарий от marat2345

Intel Fortran ?

AFAIK, как и gcc, у intel-овской коллекции компиляторов (icc) оптимизатор один и тот же что для c++, что для c, что для fortran-а.

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

Я, кстати, отнюдь не считаю C++ идеальным языком. Но с ним работать вполне можно. В отличие от.

VLev ()
Ответ на: комментарий от VLev

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

например ?

marat2345 ()
Ответ на: комментарий от marat2345

например ?

Я тогда пользовательский интерфейс для своей «универсальной программы моделирования плазмы» писал.
Практически с нуля придумал и с большим трудом реализовал сложную систему структур данных на common-блоках.
Но потом случайно обнаружил книжку Страуструпа, и с удивлением узнал, что все это уже давно придумано.
;)

VLev ()
Ответ на: комментарий от VLev

public, private, alias при импортировании имен, определенные пользователем операции..

marat2345 ()
Ответ на: комментарий от VLev

эти как вы называете «костыли» появились в Фортране90, а вы использовали 77. как можно говорить за язык программирования, который вы не использовали?

marat2345 ()
Ответ на: комментарий от marat2345

как можно говорить за язык программирования, который вы не использовали?

Я до сих пор прекрасно читаю Fortfan-овские коды любого диалекта. И вижу в них все те же проблемы, что были в моей молодости.
Кроме того, я довольно много общался с нашими Fortran-истами в то время, когда появился -90, собственно, потому и не писал на нем никогда.
Даже желания попробовать не возникало --- все они страшно плевались.
Где-то ближе к 2000-м их мнение видимо изменилось, по крайней мере несколько восторженных отзывов я слышал, но беглое знакомство с предметом этих отзывов всегда показывало тривиальные с точки зрения C++ конструкции.
Потом «восторженные отзывы» относились уже в основном к эффективности, но к этому времени я в этом предмете уже более-менее понимал.
В частности, примерно тогда и сформулировал мой основной тезис по Fortran-у, который, видимо, актуален и поныне: На C++ очень легко написать неэффективную программу, но на Fortran очень сложно написать эффективную.

VLev ()
Ответ на: комментарий от VLev

В частности, примерно тогда и сформулировал мой основной тезис по Fortran-у, который, видимо, актуален и поныне: На C++ очень легко написать неэффективную программу, но на Fortran очень сложно написать эффективную.

это не внутреняя проблема Фортрана, это внутрення проблема конкретного программиста. Как пример: коммерчески успешный научный и околонаучный софт пишется на Фортране90/95 (ANSYS, ABAQUS, LS-DYNA,...). P.S. для научных программ ООП в стиле С++ дает проигрыш простым массивам Фортрана в 2..3 раза. Вы ведь знаете про SoA и AoS.

marat2345 ()
Ответ на: комментарий от marat2345

это не внутреняя проблема Фортрана, это внутрення проблема конкретного программиста

Именно что это (вторая часть тезиса) внутренняя проблема Fortran, а вот первая --- внутренняя проблема конкретного программиста на C++.
Никто ведь не заставляет его создавать каждую новую частицу командой new, используя свой виртуальный класс для каждого сорта. ;)
А вот использовать эти самые «простые массивы» Фортран фактически заставляет. Хотя на мой взгляд, эти самые массивы как раз и есть основная причина неэффективности современных программ типа ANSYS, ABAQUS, LS-DYNA,....
Несмотря на всю их коммерческую успешность.

VLev ()
Ответ на: комментарий от VLev

эти программы работают на таких сетках, на которых LRnLA по Вашим словам работать никогда не будет. поэтому корректно ли говорить об их эффективности, есть сравнить с чем?

marat2345 ()
Ответ на: комментарий от VLev

сейчас новый Фортран позволяет писать не только в массивах. пишите если нравиться в ООП.

marat2345 ()
Ответ на: комментарий от marat2345

поэтому корректно ли говорить об их эффективности, есть сравнить с чем?

Я использую термин «эффективость» как вполне конкретный, а не абстрактный параметр: это доля от пиковой производительности компьютера. Сравнивать с 1.

работают на таких сетках, на которых LRnLA по Вашим словам работать никогда не будет

структура сетки самоцелью являться ну никак не может не может.
А те задачи, что решают subj-евые программы --- LRnLA вполне по силам.

VLev ()
Ответ на: комментарий от VLev

эти программы достаточно эффективны при расчете НДС. главная их проблема - расчет задач контактного взаимодействия, там вся эффективность падает. когда будет LRnLA для прочности (не для контактакного взаимодействия), тогда и будет разговор об эффективности Abaqus vs LRnLA, а пока «вполне по силам» както не убедительно.

marat2345 ()
Ответ на: комментарий от VLev

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

marat2345 ()
Ответ на: комментарий от marat2345

Abaqus vs LRnLA

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

VLev ()
Ответ на: комментарий от marat2345

крайне сложно в приемлемый календарный срок описать регулярной сеткой

вот этого тезиса я не понял.
Что именно сложного в «описании» регулярной сеткой?

VLev ()
Ответ на: комментарий от VLev

на всякий случай: Abaqus - как пример классической программы (не-LRnLA) моделирования сложного физического явления. Узлы сетки перемешаются, реология материалов сложная, возможны ударные волны и т.д. как следствие условие устойчивости Куранта (при решении явной схемой) будет зависить от F(характерного размера сетки, характеристики материала...). Без определения min шага по времени по всей сетки, нет смысла переходить к следующему временному слою - одно преимущество LRnLA уходит. Изза нерегулярности сетки можно построить иерархию LRnLA ?

вопрос существует алгоритм упорядочения LRnLA для произвольной сетки?

Нет и не будет. От сетки как минимум требуется структурированность.

Для меня эти пункты принципиальны, а для Вас ?

marat2345 ()
Ответ на: комментарий от VLev

а вы когда нибудь работали с чертижами ну например здания и оборудования АЭС ? :) и по ним надо построить сетку для Лагранжевого расчета (прочность). Для консольных балок и кубиков регулярные сетки легко строятся.

marat2345 ()
Ответ на: Каша в голове. от VLev

Цемент в голове

тут ошибка примерно в 2^30 раз

Этот вопрос уже решили вроде-бы?

это не так

Что не так? Вы не согласны с тем, что в том примере, с размером задачи 4000*4000x*double*4, возможности всех вариантов и уровней кэширования перекрыты на порядок?

Если кто-то поставит --- сделаю, результаты выложу...

Не думаю, что с такими задачами обратятся к вам...

Так вот там весьма много разных «классических методов оптимизации» описано, и каждый применяется во вполне определенной ситуации, и тогда лишь эффективен, а в других случаях --- нет, нужны другие

Это вполне самоочевидно. Однако, я не понимаю, почему вы сравниваете свой метод с какими-то абстрактными «обычными подходами», подозрительно похожими на тупую реализацию «в лоб» вообще без применения каких-либо оптимизаций.

И это не так, совсем не так. И в теории, и по факту

Бла-бла-бла... где пруф?

no-such-file ★★★★★ ()
Ответ на: комментарий от VLev

У Вас проблемы с формальной логикой. Тут наоборот написано о том, что все настолько «не ок», что без ПВС никак не обойтись

Это у вас проблемы с логикой. Если ваши задачи так велики, это не значит, что ситуация такова для всех. Я ни как не спорю с применением вашего метода на ПВС, а только лишь с заявлениями апологетов о том, что на обычном компе, на «маленьких задачах» будет ускорение на порядок.

Вы путаете «классические методы дискретизации» и «классические методы оптимизации». Кроме всего прочего --- это термины совершенно разных наук.

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

В этом абзаце я пытаюсь объяснить медицинский факт, наблюдаемый сплошь и рядом --- отсутствие этого самого «окея» в параллельных приложениях, написанных весьма квалифицированными программистами

А я вам привел в этой теме медицинский факт, что все ок, а ваших программистов гоните в шею.

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

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

Не так. У «обычной SMP архитектуры» масса других бутылочных горлышек. В subj-евой статье я об этом не писал, но за прошедшее время успел их изрядно изучить

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

no-such-file ★★★★★ ()
Ответ на: Цемент в голове от no-such-file

Вы не согласны с тем, что в том примере, с размером задачи 4000*4000x*double*4, возможности всех вариантов и уровней кэширования перекрыты на порядок?

4000*4000x*double*4 даёт 512M, которые в моем посте как раз и были указаны. Конкретно для Intel Core2 Quad Q6600 размеры данных 1-поточного приложения в 64бит режиме, при которых следует ожидать изменений эффективности такие: 32K/256K/4M/16M/128M/2G

Теперь по поводу Pluto. Судя по написанному в Вашей же ссылке --- там используются нестандартные приемы оптимизации, которые они сами называют «polyhedral model», что, насколько я понял, является разновидностью тайловой оптимизации.
Кстати говоря, я считаю, что именно тайлы со временем полностью вытеснят «простые массивы Fortrana», о которых речь шла вчера.
Короче --- от Pluto изначально следует ожидать неплохих показателей эффективности.

Теперь смотрим на график и видим результат 2GFlops на одном потоке.
Пиковая производительность одного ядра Intel Core2 Quad Q6600 9.6GFlops, т.е. эффективность чуть больше 20%
«В среднем по больнице» это весьма неплохой результат, но совсем не то, на что претендуют LRnLA алгоритмы.
В общем как-то так.

VLev ()
Ответ на: комментарий от no-such-file

а только лишь с заявлениями апологетов о том, что на обычном компе, на «маленьких задачах» будет ускорение на порядок.

Величина этого самого «ускорения» зависит от того, какое «замедление» было в альтернативном решении «ускоряемой» задачи.
Последнее зависит от множества факторов.
В частности, от размерности задачи. Так, для 2D задач «обычные методы оптимизации» обычно дают куда бОльший эффект, чем для 3D.

Однако для каждого конкретного случая автор «ускоряемой» программы всегда может оценить потенциал этого ускорения --- для этого достаточно самому подсчитать ту самую эффективность, о которой я тут талдычу.

VLev ()
Ответ на: комментарий от VLev

которые они сами называют «polyhedral model»,

Это стандартная оптимизация известная еще со времен царя Гороха. А вы не в курсе? Nuff said.

Пиковая производительность одного ядра Intel Core2 Quad Q6600 9.6GFlops

Не одного, а четырех. У одного 2.4GFlops

Теперь смотрим на график и видим результат 2GFlops на одном потоке

То есть около 80% пиковой.

no-such-file ★★★★★ ()
Ответ на: комментарий от no-such-file

Не одного, а четырех. У одного 2.4GFlops

учить матчасть.
Обратить особое внимание на термины: тактовая частота, конвейер, суперскалярность, векторизация.

Потом приходите --- поговорим.

VLev ()
Ответ на: комментарий от marat2345

кроме порядка доступа --- в тайлах данные еще хранить надо.

VLev ()
Ответ на: комментарий от VLev

Так, для 2D задач «обычные методы оптимизации» обычно дают куда бОльший эффект, чем для 3D

Возможно.

Однако для каждого конкретного случая автор «ускоряемой» программы всегда может оценить потенциал этого ускорения --- для этого достаточно самому подсчитать ту самую эффективность, о которой я тут талдычу

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

Кроме того, для получения высокой эффективности вычислений, вам в любом случае придётся обходить данные так, чтобы минимизировать издержки доступа, а это значит, что в итоге все сведется к той самой «polyhedral model» в каком-либо виде, т.к. чудес не бывает.

no-such-file ★★★★★ ()
Ответ на: комментарий от VLev

учить матчасть.
Обратить особое внимание на термины: тактовая частота, конвейер, суперскалярность, векторизация.

Ох, ё, с кем я общаюсь? Сначала вы подучите, сколько блоков FPU имеет одно ядро в Core2, а за одно и арифметику 2.4ГГц*4ядра=9.6Гфлопс

Потом приходите --- поговорим.

no-such-file ★★★★★ ()
Ответ на: комментарий от no-such-file

Это стандартная оптимизация известная еще со времен царя Гороха. А вы не в курсе?

нет. За ссылку, кстати, спасибо. Мне они сейчас нужны.

ваш метод является безальтернативно эффективным и не имеет никаких конкурентов.

Дело в том, что насколько я понимаю, AIv тут в основном занимается рекламой LRnLA. А сам я так очень далёк от обычных «рекламных» недоговорок и преувеличений и если говорю об эффективности, ускорении, безальтернативности и проч., то либо в конкретном контексте, либо с множеством оговорок (т.е. пользуясь обычным методом ведения научных дискуссий).
По факту --- для продвижения метода в массы, да и просто его развития --- это оказалось плохо, и скорее всего он повторит обычную для науки динамику: новые знания завоёвывают умы со скоростью вымирания представителей предыдущего поколения учёных...

VLev ()
Ответ на: комментарий от ckotinko

nginx работает тупо в одном потоке.

nginx работает в несколько процессов (one master + n workers). Сколько ядер и воркеров было у них я, конечно, не знаю.

quasimoto ★★★★ ()
Ответ на: комментарий от quasimoto

КО летит на помощь

nginx принимает соединения в одном потоке. он явно уперся в этот поток. ЗЫ: не хватает сведений о загрузке процессоров.

ckotinko ☆☆☆ ()
Ответ на: комментарий от no-such-file

Да ладно, со всеми бывает.

Чтобы закончить тему однопоточного FDTD, я приведу табличку результатов тестов 3D FDTD для Максвелла с токами из диплома моей бывшей студентки совсем не программистской специальности. тестируемый FDTD-шный блок входит в 3D3V PIC код, который был написан ей самой за пол-года примерно. Естественно с использованием LRnLA алгоритмов.

Maxwell,15*,27+         clocks  GFLOPs  Eff(+)  AVX             clocks  GFLOPs  Eff(+)  AVX     
float           1       29.6    4.68    91.2%                   34.1    4.06    79.2%           
Float[4]        4       9.54    14.53   70.8%   3.10            10.84   12.79   62.3%   3.15    
Float[8]        8       7.72    17.95   43.7%   1.24    3.8     9.23    15.02   36.6%   1.17    3.7
double          1       32.5    4.26    83.1%                   37.9    3.66    71.2%           
Double[2]       2       19.3    7.18    69.9%   1.68            21.8    6.36    61.9%   1.74    
Double[4]       4       15.9    8.72    42.5%   1.21    2.0     18.6    7.45    36.3%   1.17    2.0
                Gcc 4.5                                 Gcc 4.6                         
+Current,18*,18+        clocks  GFLOPs  Eff(+)  AVX             clocks  GFLOPs  Eff(+)  AVX     
float           1       55.26   4.66    81.4%                   61      4.22    73.8%           
Float[4]        4       18      14.30   62.5%   3.07            20.2    12.74   55.7%   3.02    
Float[8]        8       14.96   17.21   37.6%   1.20    3.7     17.14   15.02   32.8%   1.18    3.6
double          1       61.43   4.19    73.3%                   67.08   3.84    67.1%           
Double[2]       2       38.3    6.72    58.7%   1.60            42.25   6.09    53.3%   1.59    
Double[4]       4       33.4    7.71    33.7%   1.15    1.8     36.88   6.98    30.5%   1.15    1.8
Результаты для core i5-2400@3.3GHz для разных базовых версий данных, в том числе и векторизованных, двух схем (с токами и в вакууме), и двух версий gcc: 4.5 и 4.6. Кстати, для 4.6 тут опции неправильные стояли, я потом разобрался с ним. На всякий случай я протестировал на том же компьютере subj-евый тест pluto для сетки 4000x4000. результаты такие: 2.28/1.82/2.55GFlops для base/pluto/tuned версий соответственно Самое смешное тут в том, что base-версия оказалась быстрее pluto-вой без тюнинга. Ну и чтобы оценить юмор этих pluto-вых тестов в полной мере, я все-таки приведу содержательную часть их тестового кода:
for(t=0; t<tmax; t++)  {
  for (j=0; j<ny; j++)
    ey[0][j] = t;
  for (i=1; i<nx; i++)
    for (j=0; j<ny; j++)
      ey[i][j] = ey[i][j] - 0.5*(hz[i][j]-hz[i-1][j]);
  for (i=0; i<nx; i++)
    for (j=1; j<ny; j++)
      ex[i][j] = ex[i][j] - 0.5*(hz[i][j]-hz[i][j-1]);
  for (i=0; i<nx; i++)
    for (j=0; j<ny; j++)
      hz[i][j]=hz[i][j]-0.7*(ex[i][j+1]-ex[i][j]+ey[i+1][j]-ey[i][j]);
 }

VLev ()
Ответ на: КО летит на помощь от ckotinko

nginx принимает соединения в одном потоке. он явно уперся в этот поток.

Не, не в одном потоке - обычно ставят количество процессов = количеству ядер. Итого, процесс master раздаёт соединения процессам воркерам, которые ядро раскидывает по ядрам так, как считает нужным. Ну и рантайм GHC тоже работает в фиксированном количестве потоков (например, +RTS -N4 -RTS), так что если nginx упрётся в свои четыре, например, воркера (= процесса = потока), то и GHC с тем же успехом может это сделать. Тут их мало что отличает - только внутрення модель обработки соединений (event loop на базе *pool и такой же event loop в IO manager + лёгкие процессы).

quasimoto ★★★★ ()
Ответ на: комментарий от ckotinko

он в accept уперся

Пруф, что accept делает master, а не worker?

Ну и snap делает accept в основном треде и ответы в форках, так что в контексте сравнения с nginx всё это не важно (если nginx упрётся в accept, то и snap тоже должен).

quasimoto ★★★★ ()
Ответ на: комментарий от geekless

Ну и отдельно не удержусь и пну, какими средствами в C++ реализуется «модульность». Заголовчные файлы — это модно и прогрессивно, чо.

Ну так есть же возможность динамической подгрузки shared library с нужным функционалом

cvs-255 ★★★★★ ()
Ответ на: комментарий от geekless

бедность выразительных средств языка. Системы типов, в частности.

А какие тебе типы, встроенные в сам язык, нужны?

cvs-255 ★★★★★ ()
Ответ на: комментарий от ckotinko

Unlike traditional servers, Nginx doesn't rely on threads to handle requests

Зато он rely on processes:

$ ps ax | grep nginx
 1447 ?        Ss     0:00 nginx: master process /usr/sbin/nginx
 1459 ?        S      0:00 nginx: worker process
 1460 ?        S      0:00 nginx: worker process
 1461 ?        S      0:00 nginx: worker process
 1462 ?        S      0:00 nginx: worker process

если accept делает worker, то оно масштабируется по ядрам.

Ну и snap тоже doesn't rely on [OS] threads to handle requests / делает accept в одном треде.

quasimoto ★★★★ ()
Ответ на: комментарий от cvs-255

а ты предлагаешь засунуть это все прямо в какой-то оператор ЯП?

split :: Eq a => [a] -> [a] -> [[a]]

mix_mix ★★★★★ ()
Ответ на: комментарий от sv75

Да ладно

Стивенс «Unix, разработка сетевых приложений», 4.8. Параллельные серверы, например. Там такой пример:

pid_t pid;
int sock, conn;

sock = socket(...);
bind(sock, ...);
listen(sock, ...);

for (;;) {
    conn = accept(sock, ...);

    pid = fork();
    if (pid == 0) {
        close(sock);
        /* handle conn */
        close(conn);
        exit(0);
    }

    close(conn);
}
quasimoto ★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.