Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, сипласплас, Вы писали:
С>>При чем здесь сборка мусора? А между ними что будем делать с изменением ссылок в разных потоках? GZ>А в чем проблема то? Адрес экземпляра объекта "неизменяемо". Единственный кто может его изменить — GC. Присваивание int — атомарно на аппаратном уровне. Так в чем дело?
[]
С>>Ты у себя в программе вот так спокойно делаешь с поинтерами, к которым идет доступ из разных тредов?
R>На x86 да, а почему бы и нет? Это экстремально быстро.
remark, а memory barrier? Или это я один тут параноик?
R>>>>> R>>> R>
Здравствуйте, eao197, Вы писали:
E>Например, механизм producer/consumer с большими объемами данных. Скажем, видеопроигрыватель, где процесс подкачки данных с диска занимает очередной буфер и заполняет его, а процесс восспроизведения не может получить доступ к буферу до окончания закачки.
Процесс подкачки данных занимает буфер и заполняет его. По окончании передает владение над ним процессу воспроизведения (в виде сообщения). Единственный выигрыш, что ожидание не надо делать вручную. Мьютекс не нужен. Состояние ожидания сообщения, и это и есть уже готовое ожидание.
E>Какие выигрышы (жи/ши пиши через и, а жы/шы — через ы?) даст здесь обмен сообщениями по сравнению с ожиданием на cond_var/mutex-е?
Да никаких. Речь в изначальном посте вообще-то шла о том, как современной программе загрузить десятки процессоров. Описанная тобой задача в принципе не загрузит больше двух.
Речь не идет о том, чтобы Erlang автоматически за тебя что-то сделал. Речь о том, что то же самое делается удобнее. Параллелит-то всё еще программист. Только шанс допустить ошибку куда меньше, чем забыть захватить мьютекс или захватить его на излишне долгое время и тем самым затормозить программу.
Например, какие изменения тебе нужно внести в архитектуру, чтобы проигрыватель мог послать «напоминание» и получить частично заполненный буфер, чтобы пользователь не увидел подвисания картинки, в надежде что задержка чтения временная и вот-вот все нормализуется? Сменить блокирующее ожидание сокета на свой цикл проверки, чтобы был появился шанс проверить флаг?
В архитектуре изолированных процессов, producer получает сообщение от сокета о приеме данных, и добавляет в буфер, или получает сообщение от проигрывателя, и отдает частично заполненный. Расширение делается добавлением всего одного сообщения.
Здравствуйте, сипласплас, Вы писали:
С>не забывай про необходимый memory barrier
А что memory barrier? Это всего лишь еще одна ссылка на тот же адрес. Даже если они будут различаться с хранящейся в OЗУ, после сборки выполнение продолжится, и будет присвоен корректный адрес. Атомарность не пострадает.
Здравствуйте, Кодёнок, Вы писали:
E>>Например, механизм producer/consumer с большими объемами данных. Скажем, видеопроигрыватель, где процесс подкачки данных с диска занимает очередной буфер и заполняет его, а процесс восспроизведения не может получить доступ к буферу до окончания закачки.
Кё>Процесс подкачки данных занимает буфер и заполняет его. По окончании передает владение над ним процессу воспроизведения (в виде сообщения). Единственный выигрыш, что ожидание не надо делать вручную. Мьютекс не нужен. Состояние ожидания сообщения, и это и есть уже готовое ожидание.
Ожидание в любом случае придется делать вручную. Будет ли это mutex.acquire или receive->BUFFER_READY.
Только вот при работе с mutex-ом у тебя один системный вызов. При передаче сообщения -- несколько, поскольку сообщение нужно синхронизировать доступ к очереди сообщений.
E>>Какие выигрышы (жи/ши пиши через и, а жы/шы — через ы?) даст здесь обмен сообщениями по сравнению с ожиданием на cond_var/mutex-е?
Кё>Да никаких. Речь в изначальном посте вообще-то шла о том, как современной программе загрузить десятки процессоров. Описанная тобой задача в принципе не загрузит больше двух.
Это уже придирки.
Кё>Речь не идет о том, чтобы Erlang автоматически за тебя что-то сделал. Речь о том, что то же самое делается удобнее. Параллелит-то всё еще программист. Только шанс допустить ошибку куда меньше, чем забыть захватить мьютекс или захватить его на излишне долгое время и тем самым затормозить программу.
На основании какого опыта в Erlang вы делаете такие утверждения?
Кё>Например, какие изменения тебе нужно внести в архитектуру, чтобы проигрыватель мог послать «напоминание» и получить частично заполненный буфер, чтобы пользователь не увидел подвисания картинки, в надежде что задержка чтения временная и вот-вот все нормализуется? Сменить блокирующее ожидание сокета на свой цикл проверки, чтобы был появился шанс проверить флаг?
Кё>В архитектуре изолированных процессов, producer получает сообщение от сокета о приеме данных, и добавляет в буфер, или получает сообщение от проигрывателя, и отдает частично заполненный. Расширение делается добавлением всего одного сообщения.
Если в архитектуре изолированных процессов producer выполняет блокирующие операции ввода-вывода, вы можете отсылать ему сообщения сколько угодно.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, сипласплас, Вы писали:
С>>не забывай про необходимый memory barrier GZ>А что memory barrier? Это всего лишь еще одна ссылка на тот же адрес. Даже если они будут различаться с хранящейся в OЗУ, после сборки выполнение продолжится, и будет присвоен корректный адрес. Атомарность не пострадает.
При чем здесь _сборка_? Я вот про что (как назло, где Wolfhound, где IT, где Vlad наконец? Неужели обязательно надо написать "с++ рулит!!!" что-бы они тут же подоспели?):
public class SharedResource{}
public class test
{
SharedResource _shared = new SharedResource();
Thread _thread = null;
void Start()
{
_thread = new Thread( new ThreadStartDelegate(this.ThreadProc) );
Sleep(1000);
_shared = null;
Sleep(1000);
_thread.Join();
}
private void ThreadProc()
{
//а тут мы вовсю юзаем _thread...
}
}
Здравствуйте, eao197, Вы писали:
E>Remark писал не о том, насколько хорошо работает на многоядерных машинах ОС и насколько отшлифован в ней шедулер. А о том, как быть программисту, когда в его распоряжении оказывается несколько процессоров.
Ему надо было точно разграничить области: прикладная область программирования и системная область программирования. Иначе получился абстрактный призыв ко всем слоям населения, охваченным электрическими сетями.
E>Например. В случае одного ядра выгодно было выделять отдельные нити для выполнения операций ввода-вывода. Скажем на отдельной нити работает ACE_Reactor, который прослушивает N сокетов и активирует M ACE_Event_Handler-ов. Event_Handler-ы вычитывают данные из сокета, оформляют их в сообщения и ставят в очередь сообщений другой нити для обработки. А так же извлекают из своих очередей сообщений сообщения с исходящими данными в своих методах handle_output (когда Reactor обнаруживает готовность сокета к записи). На одном ядре схема работает отлично.
E>Но, на двух ядрах оказывается, что стоимость переключения контекста между нитью-обработчиком и нитью ACE_Reactor-а слишком высока, чтобы передавать входящий/исходящий трафик через очереди сообщений.
E>Вопрос в том, как перепроектировать подобное приложение на два/четыре/восемь ядер сейчас так, чтобы при появлении 80(!) ядер приложение не пришлось перепроектировать с нуля заново.
Я не знаю, что такое "ACE_Reactor" -- впервые слышу об этой идиоме программирования. И всё, что с ней связано, скорее всего, относится к практическому аспекту конкретной реализации какой-то сущности. Так что индуцировать на её основе принципы ДЛЯ_ВСЕХ не имеет смысла. Она может быть использована лишь как пример, но не эталон (не)применимости.
Здравствуйте, Кодёнок, Вы писали:
Кё>Здравствуйте, LaptevVV, Вы писали:
Кё>>> Алгоритм для многих исполнителей — я о таком не слышал. Кё>Там целый большой сайт Куда именно смотреть?
А там действительно много всего о параллельных алгоритмах.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, сипласплас, Вы писали:
С>>>Ты у себя в программе вот так спокойно делаешь с поинтерами, к которым идет доступ из разных тредов?
R>>На x86 да, а почему бы и нет? Это экстремально быстро.
С>remark, а memory barrier? Или это я один тут параноик?
Нет, я тоже параноик.
Но на x86 тут можно и нужно делать без барьеров.
Здравствуйте, сипласплас, Вы писали:
С>Здравствуйте, GlebZ, Вы писали:
GZ>>Здравствуйте, сипласплас, Вы писали:
С>>>не забывай про необходимый memory barrier GZ>>А что memory barrier? Это всего лишь еще одна ссылка на тот же адрес. Даже если они будут различаться с хранящейся в OЗУ, после сборки выполнение продолжится, и будет присвоен корректный адрес. Атомарность не пострадает.
С>При чем здесь _сборка_? Я вот про что (как назло, где Wolfhound, где IT, где Vlad наконец? Неужели обязательно надо написать "с++ рулит!!!" что-бы они тут же подоспели?):
С>
С>public class SharedResource{}
С>public class test
С>{
С> SharedResource _shared = new SharedResource();
С> Thread _thread = null;
С> void Start()
С> {
С> _thread = new Thread( new ThreadStartDelegate(this.ThreadProc) );
С> Sleep(1000);
С> _shared = null;
С> Sleep(1000);
С> _thread.Join();
С> }
С> private void ThreadProc()
С> {
С> //а тут мы вовсю юзаем _thread...
С> }
С>}
С>
После "захвата" _shared в ThreadProc() надо просто проверить на null. InterlockedXXX здесь не нужен.
И это надо сделать в люом случае в такой ситуации, даже если обращения к _shared защищено мьютексами.
Здравствуйте, iZEN, Вы писали:
E>>Remark писал не о том, насколько хорошо работает на многоядерных машинах ОС и насколько отшлифован в ней шедулер. А о том, как быть программисту, когда в его распоряжении оказывается несколько процессоров.
ZEN>Ему надо было точно разграничить области: прикладная область программирования и системная область программирования. Иначе получился абстрактный призыв ко всем слоям населения, охваченным электрическими сетями.
Я не помню, чтобы remark говорил что-нибудь о разработке ОС в условиях многоядерности.
Чтоже до деления на прикладное и системное программирование...
Вот, например, сервера БД и встраиваемые БД -- это системное или прикладное программирование?
А компиляторы?
А Web-сервера?
ZEN>Я не знаю, что такое "ACE_Reactor" -- впервые слышу об этой идиоме программирования. И всё, что с ней связано, скорее всего, относится к практическому аспекту конкретной реализации какой-то сущности. Так что индуцировать на её основе принципы ДЛЯ_ВСЕХ не имеет смысла. Она может быть использована лишь как пример, но не эталон (не)применимости.
Мне кажется, вам самому нужно определиться с тем, что вы хотели сказать. Судя по всему, многие читатели поняли, о чем говорил remark. Вы же насоветовали ему лучше ознакомиться с Solaris, LWP, TLS и пр. Хотя суть этого совета от меня ускользнула.
ACE_Reactor -- это C++ный фреймворк в составе библиотеки ACE. Он берет на себя задачу контроля за состоянием N дескрипторов каналов ввода/вывода (под Unix-ом это могут быть пайпы, сокеты, файлы, под Windows -- сокеты/пайпы). За каждый канал должен отвечать специальный объект-наследник ACE_Event_Handler. Т.е. ACE_Reactor работает в качестве мультиплексора (или демультиплексора -- путаюсь в этих терминах) событий.
В простейшем случае ACE_Reactor является оберткой над while{} c select-ом внутри. Когда канал переходит в состояние готовности к чтению, Reactor вызывает у соответствующего Event_Handler-а метод handle_input. Когда канал переходит в состояние готовности к записи -- вызывается метод handle_output. И т.д.
ACE_Reactor используется в качестве базового слоя при реализации различных реактивных (т.е. реагирующих на происходящие события) сетевых служб. А уже что это будут за службы -- служба синхронизации времени, Web-сервер, сервер БД, балансировщих нагрузки или еще что -- зависит от задачи.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, GlebZ, Вы писали:
R>>Меня лично на PIV3.0+1Гб не устраивает скорость компиляции, GZ>У меня тормозит компиляция NET, только когда много сборок. Теже файлы но в одной сборке компилируются мухой. Соответсвенно вывод что проблема в диск+скорость кэша(то бишь доступа к озу). GZ>Что касается С++, то там те же проблемы. Дополнительный проц не сильно увеличит скорость компиляции.
Вы сами проверяли?
А я проверял. Двухъядерный процессор рвёт одноядерный на одной и той же частоте (Athlon64 X2 2ГГц vs. AthlonXP 1,8ГГц) в компиляции исходников C/C++ компилятором GCC более чем в 2,5 раза (двадцать пять минут против полутора часов) -- масштабируемость фактически линейная при одинаковой латентности подсистмы памяти и кэша L2).
R>>не устраивает скорость работы навороченных GUI типа Open Office/MS Visual Studio, GZ>Основные проблемы память+диск. R>>не устраивает скорость запуска очень многих программ. GZ>Основные проблемы память+диск.
Для этого придумали различные QuickStart'ы. Для OpenOffice есть. Недавно анонсирован и для последней версии JRE: http://www.linux.org.ru/jump-message.jsp?msgid=2192306
Но всё это костыли. Если всё рабочее окружение отправить в своп, а при загрузке компьютера оотуда всё доставать в оперативку... Но можно использовать энергонезависимое ОЗУ большой ёмкости (несколько гигабайт) и отказаться от винчестера вообще, тогда все установленые приложения и система фактически имеют включенную готовность, как радиоприёмник.
Здравствуйте, сипласплас, Вы писали:
С>по моим сведениям присванивание ссылки в c# — атомарно. Кроме того, нужно делать memory barrier. А он делается с пом. InterlockedXXX — синхронизация кешей
Твои сведения сильно ошибочные. Если ты сохранишь значение ссылки в переменной, которая видна потоку на другом ядре и не сделаешь в явном виде барьер памяти — это будет очень большой ошибкой.
Ты хотя бы представляешь себе потери в производительности, если каждое присваивание ссылки будет сделано через InterlockedExchange, который является full fence?
Здравствуйте, iZEN, Вы писали:
ZEN>Здравствуйте, GlebZ, Вы писали:
R>>>Меня лично на PIV3.0+1Гб не устраивает скорость компиляции, GZ>>У меня тормозит компиляция NET, только когда много сборок. Теже файлы но в одной сборке компилируются мухой. Соответсвенно вывод что проблема в диск+скорость кэша(то бишь доступа к озу). GZ>>Что касается С++, то там те же проблемы. Дополнительный проц не сильно увеличит скорость компиляции.
ZEN>Вы сами проверяли? ZEN>А я проверял. Двухъядерный процессор рвёт одноядерный на одной и той же частоте (Athlon64 X2 2ГГц vs. AthlonXP 1,8ГГц) в компиляции исходников C/C++ компилятором GCC более чем в 2,5 раза (двадцать пять минут против полутора часов) -- масштабируемость фактически линейная при одинаковой латентности подсистмы памяти и кэша L2).
Дак и VS2005 это _умеет_. Вам неочевидно почему этого не умеет VS2003? Не из-за винды же...
Здравствуйте, Andrei F., Вы писали:
AF>Здравствуйте, сипласплас, Вы писали:
С>>по моим сведениям присванивание ссылки в c# — атомарно. Кроме того, нужно делать memory barrier. А он делается с пом. InterlockedXXX — синхронизация кешей
AF>Твои сведения сильно ошибочные.
Ошибочные в том, что при любое присваивание ссылки ведет к full fence?
AF>Если ты сохранишь значение ссылки в переменной, которая видна потоку на другом ядре и не сделаешь в явном виде барьер памяти — это будет очень большой ошибкой.
Спасибо
AF>Ты хотя бы представляешь себе потери в производительности, если каждое присваивание ссылки будет сделано через InterlockedExchange, который является full fence?
Здравствуйте, remark, Вы писали:
R>Здравствуйте, сипласплас, Вы писали:
[]
R>После "захвата" _shared в ThreadProc() надо просто проверить на null. InterlockedXXX здесь не нужен. R>И это надо сделать в люом случае в такой ситуации, даже если обращения к _shared защищено мьютексами.
А если заменить _shared = null на _shared = new SharedResource()? Ты понял о чем я?
R>
Здравствуйте, remark, Вы писали:
R>Здравствуйте, сипласплас, Вы писали:
С>>>>Ты у себя в программе вот так спокойно делаешь с поинтерами, к которым идет доступ из разных тредов?
R>>>На x86 да, а почему бы и нет? Это экстремально быстро.
С>>remark, а memory barrier? Или это я один тут параноик?
R>Нет, я тоже параноик. R>Но на x86 тут можно и нужно делать без барьеров.
Здравствуйте, eao197, Вы писали:
E>>>Remark писал не о том, насколько хорошо работает на многоядерных машинах ОС и насколько отшлифован в ней шедулер. А о том, как быть программисту, когда в его распоряжении оказывается несколько процессоров.
iZEN>>Ему надо было точно разграничить области: прикладная область программирования и системная область программирования. Иначе получился абстрактный призыв ко всем слоям населения, охваченным электрическими сетями.
E>Я не помню, чтобы remark говорил что-нибудь о разработке ОС в условиях многоядерности.
E>Чтоже до деления на прикладное и системное программирование... E>Вот, например, сервера БД и встраиваемые БД -- это системное или прикладное программирование?
Это прикладное программирование.
E>А компиляторы?
Прикладное.
E>А Web-сервера?
Прикладное.
Что системное программирование: то, что работает в режиме ядра -- это прежде всего драйверы и шедулер аппаратных потоков исполнения.
iZEN>>Я не знаю, что такое "ACE_Reactor" -- впервые слышу об этой идиоме программирования. И всё, что с ней связано, скорее всего, относится к практическому аспекту конкретной реализации какой-то сущности. Так что индуцировать на её основе принципы ДЛЯ_ВСЕХ не имеет смысла. Она может быть использована лишь как пример, но не эталон (не)применимости.
E>Мне кажется, вам самому нужно определиться с тем, что вы хотели сказать. Судя по всему, многие читатели поняли, о чем говорил remark. Вы же насоветовали ему лучше ознакомиться с Solaris, LWP, TLS и пр. Хотя суть этого совета от меня ускользнула.
Да только что нашёл в Google, что такое ACE. Примочка на C++ для решения вдруг возникших проблем с управлением нагрузкой многоядерных процессоров.
E>ACE_Reactor -- это C++ный фреймворк в составе библиотеки ACE. Он берет на себя задачу контроля за состоянием N дескрипторов каналов ввода/вывода (под Unix-ом это могут быть пайпы, сокеты, файлы, под Windows -- сокеты/пайпы). За каждый канал должен отвечать специальный объект-наследник ACE_Event_Handler. Т.е. ACE_Reactor работает в качестве мультиплексора (или демультиплексора -- путаюсь в этих терминах) событий.
E>В простейшем случае ACE_Reactor является оберткой над while{} c select-ом внутри. Когда канал переходит в состояние готовности к чтению, Reactor вызывает у соответствующего Event_Handler-а метод handle_input. Когда канал переходит в состояние готовности к записи -- вызывается метод handle_output. И т.д.
E>ACE_Reactor используется в качестве базового слоя при реализации различных реактивных (т.е. реагирующих на происходящие события) сетевых служб. А уже что это будут за службы -- служба синхронизации времени, Web-сервер, сервер БД, балансировщих нагрузки или еще что -- зависит от задачи.
На его основе что-либо системное сделали (работающее в ядре ОС) или делают только приложения, так как на основе Pthreads и LWP? (Инетресуюсь, потому что хочу провести/или не провести черту применимости ACE между системным и прикладным использованием)
Здравствуйте, remark, Вы писали:
R>>>А если разрешено, то тут не надо никаких InterlockedXXX, просто присвоить/считать значение указателя.
С>>Ты у себя в программе вот так спокойно делаешь с поинтерами, к которым идет доступ из разных тредов?
R>На x86 да, а почему бы и нет? Это экстремально быстро.
Тут будет возможна ситуация, когда на другом ядре обновленное значение указателя уже будет в кэше, а сами данные, на которые он указывает — нет. Поэтому на многоядерной системе так делать нельзя. На одноядерной можно, но тоже есть ограничение — переменная с указателем должна быть правильно выровнена.