> UPD: Забыл сказать - доступ к элементу пула должет быть > именно по индексу, а не по адресу обекта пула. Поэтому > одного SLIST (когда бы Index_in_pool включал бы указатель > на ptr = new Pool_entry_t() вместо индекса) без > Pool_entry_t m_pool[pool_size] недостаточно. Это часть > бизнес логики.
Хм. Интересно а в чем логика? Я то уж было ломанулся исправлять явно лишнее индексирование :-)
А вообще только что пришла идея: для каждого процессора выделить свой лист свободных индексов. Если выделение произошло на одном процессоре, а возврат на другом - это ожидаемо и нормально. Если пул у какого нибудь процессора закончится, то тогда уж и делать stop-the-world и балансировать пулы, предполагается, что если выделения/освобождения распределены более менее равномерно, то листы свободных индексов для каждого процессора будут примерно равными по длине.
Осталось найти недорогой способ получения номера текущего процессора, но думаю это непривилегированная операция и может быть выполнена без ухода в ядро. Кроме того, нужно придумать способ лочить очередь без захвата шины (уже в однопроцессорном окружении), но на мой взгляд это довольно легко.
Ну и после всех этих манипуляций придется проверять дают ли они хоть какой то выигрыш :-)
UPD: Забыл сказать - доступ к элементу пула должет быть именно по индексу, а не по адресу обекта пула. Поэтому одного SLIST (когда бы Index_in_pool включал бы указатель на ptr = new Pool_entry_t() вместо индекса) без Pool_entry_t m_pool[pool_size] недостаточно. Это часть бизнес логики.
Ищется таковой. Чтобы было просто, и самое главное работало быстро (без высокого контеншн) для 5-10 thread-ов на multi-core box. Самое тривиальное, что приходит на ум - ниже. Сейчас очень модно lock-free решения. Может кто подскажет альтернативу тому, что ниже?
> UPD: Забыл сказать - доступ к элементу пула должет быть > именно по индексу, а не по адресу обекта пула. Поэтому > одного SLIST (когда бы Index_in_pool включал бы указатель > на ptr = new Pool_entry_t() вместо индекса) без > Pool_entry_t m_pool[pool_size] недостаточно. Это часть > бизнес логики.
Хм. Интересно а в чем логика? Я то уж было ломанулся исправлять явно лишнее индексирование :-)
А вообще только что пришла идея: для каждого процессора выделить свой лист свободных индексов. Если выделение произошло на одном процессоре, а возврат на другом - это ожидаемо и нормально. Если пул у какого нибудь процессора закончится, то тогда уж и делать stop-the-world и балансировать пулы, предполагается, что если выделения/освобождения распределены более менее равномерно, то листы свободных индексов для каждого процессора будут примерно равными по длине.
Осталось найти недорогой способ получения номера текущего процессора, но думаю это непривилегированная операция и может быть выполнена без ухода в ядро. Кроме того, нужно придумать способ лочить очередь без захвата шины (уже в однопроцессорном окружении), но на мой взгляд это довольно легко.
Ну и после всех этих манипуляций придется проверять дают ли они хоть какой то выигрыш :-)
В принципе достаточно много задач, где нужно клиенту...28.03.09 06:25 Автор: void <Grebnev Valery> Статус: Elderman Отредактировано 28.03.09 06:26 Количество правок: 1
> Хм. Интересно а в чем логика? Я то уж было ломанулся > исправлять явно лишнее индексирование :-)
В принципе достаточно много задач, где нужно клиенту отдавать индекс, а не адрес. В той задаче, для которой это сейчас делается - для храния имеетсятолько WORD. Получив новый объект из пула, клиент будет проводить типа CAS над этим индексом, чтобы удостовериться, что использует один и тот же shared буфер, который уже захвачен другим клиентом. Типа как общий объект, буфер, и т.д для нескольких клиентов. Другого рода задачи всплывают в IPC на shared memory, когда сервер отдаёт клиенту "номер" shared канала. Можно конечно, получив ::InterlockedPopEntrySList адрес затем мапить или хеш мапить его на индекс, но это может быть не бесплатно. Хотя конечно надо тестировать.
> А вообще только что пришла идея: для каждого процессора > выделить свой лист свободных индексов.
Идея хорошая и не только для данной задачи. Надо об этом подумать ;-)
> Кроме того, нужно > придумать способ лочить очередь без захвата шины (уже в > однопроцессорном окружении), но на мой взгляд это довольно > легко.
А как? ... Саттер не так давно написал нескольно статей по этому поводу. Но я признаться не смотрел.
Саттера не читал, но мнение имею [upd]28.03.09 08:48 Автор: amirul <Serge> Статус: The Elderman Отредактировано 28.03.09 09:14 Количество правок: 1
> > Кроме того, нужно > > придумать способ лочить очередь без захвата шины (уже > в > > однопроцессорном окружении), но на мой взгляд это > довольно > > легко. > > А как? ... Саттер не так давно написал нескольно статей по > этому поводу. Но я признаться не смотрел.
Саттера не читал, но мнение имею
Вообще интуиция подсказывает, что обычный CMPXCHG (без префикса LOCK) - должен отлично сработать. Я могу ошибаться, но насколько я понимаю поток может быть вытеснен только между инструкциями, а не прямо посреди (если прерывание приходит посреди инструкции, то процессор дожидается окончания этой инструкции) - а для однопроцессорной среды этого достаточно для обеспечения атомарности. Соответственно, когда флаг, блокирующий очередь для процессора (одна очередь - один флаг) не получается "захватить" - отдаем квант чем то вроде sleep(0) или подобным и делаем спин. Огромная стоимость такой операции для ожидающего потока будет нивелироваться крайне низкой вероятностью рейса на участке из десятка инструкций (pop из односвязного списка и освобождение очереди).
-------------------
Кстати, о текущем процессоре. В Win2k3 появилась полезная функция GetCurrentProcessorNumber. Вот так выглядит версия из Win7 (в других скорее всего что то подобное):
Так что болдом выделено конкретно получение номера процессора. Висты сейчас под рукой нет - проверить не могу, но как я уже сказал вряд ли она уходит в ядро, так что можно смело использовать эту функцию - оверхед на IPI и коллизии по идее должен быть больше. Так что можно сделать более продуктивную версию для 2k3+ с откатом к бейскейс реализации на interlocked-очереди для 2k/xp