Re[5]: Многопоточность сегодня
От: remark Россия http://www.1024cores.net/
Дата: 11.10.07 17:21
Оценка: 35 (3)
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, сипласплас, Вы писали:


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).
Плюс шина межпроцессорного/межядерного взаимодействия может стать боттлнеком, так что приложение просто не будет масштабироваться вообще при добавлении ядер, даже если потоков/работы достаточно, и нет сериализации на мьютексах, ядра не загружены и шина памяти не загружена.



1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.