Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, сипласплас, Вы писали:
E>>>Но, на двух ядрах оказывается, что стоимость переключения контекста между нитью-обработчиком и нитью ACE_Reactor-а слишком высока, чтобы передавать входящий/исходящий трафик через очереди сообщений.
С>>При чем здесь это? Чем оно дороже чем на одноядерной машине?
К>Дороговизна не в переключениях, а в атомарных операциях.
К>Комплект функций синхронизации — атомарные операции, мьютексы-шмютексы — предоставляемый операционной системой приложению, различается для одно- и многоядерных систем.
К>На 1 ядре atomic_xxx — это
К>- запретить прерывания — чтобы планировщик не вломился и не вытеснил поток
К>- выполнить операцию
К>- разрешить прерывания
Не могу не вмешаться

Скажу за x86.
На 1 ядре atomic_xxx — это
— запрещать прерывания не надо — т.к. операции, которые выполняются как атомарные, всегда состоят из одной машинной команды, а прерывания не действуют на уровне микрокоманд
— выполнить операцию
Хотя тут некоторая загвоздка. Т.к. что бы добиться такого эффекта надо либо компилировать свою программу исключительно под одно ядро, либо делать как в ACE — при старте программы смотрим сколько ядер в системе и устанавливаем соотв. обрабом глобальные указатели на правильные функции atomic_xxx.
Итого это занимает порядка тактов.
Если использоват "честные" atomic_xxx, то даже на одноядерном процессоре Intel это выливается в 100 тактов.
К>А на многоядерном — это
К>- запретить прерывания
К>- заблокировать память — чтобы остальные ядра туда не выстрелили
К>- выполнить операцию
К>- разблокировать память
К>- разрешить прерывания
А на многоядерном — это
— запретить прерывания — опять не надо
— заблокировать память/или строку кэша, что немного дешевле и масштабируемее
— выполнить операцию
— разблокировать память/строку кэша
Итого это занимает порядка 100 — 450 тактов (в зависимости от статуса кэш линии)
Но основная беда даже не в этом.
(опустим пока такие тривиальные вещи как сериализация на мьютексах)
Передача кэш-линии занимает порядка 150-350 тактов. Даже без всяких атомарных операций и пр.
Т.е. скорость работы снижается до 100 (!) раз. Т.о. тривиальный producer-consumer может стать ботлнеком, если данные просто переходят из одного кэша в другой (без всяких atomic, мьютексов, евентов, вызовов я ядро для пробуждения consumer).
Плюс шина межпроцессорного/межядерного взаимодействия может стать боттлнеком, так что приложение просто не будет масштабироваться вообще при добавлении ядер, даже если потоков/работы достаточно, и нет сериализации на мьютексах, ядра не загружены и шина памяти не загружена.