GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 20.01.08 16:33
Оценка:
Как получить функциональность GetCurrentProcessorNumber()/NtGetCurrentProcessorNumber() под WinXP/2k?

Поиск дал следующие результаты.
1.
__declspec(naked) unsigned get_current_proc()
{
    __asm
    {
        mov ecx, 03Bh
        lsl eax, ecx
        shr eax, 0Eh
        retn
    }
}

Но как я понял, это будет работать только на тех версиях Windows, где работает и GetCurrentProcessorNumber(). Т.е. не будет работать под WinXP/2k.

2. С помощью инструкции CPUID получать номер APIC ID, по статической таблице переводить его в номер процессора. Это будет работать на всех версиях Windows. Практически то, что нужно, мне даже переводить в номер процессора не нужно, и так устроит, главное иметь уникальное число для каждого процессора.
Но тут полностью не устраивает, что на моём компьютере CPUID с EAX=1 выполняется 284 такта (полностью сериализует конвеер и выполняет полный барьер памяти).


В идеале хотелось чего-то вроде получения идентификатора текущего потока из блока информации потока.


з.ы. Не уверен, куда это больше — к WinAPI или Низкоуровнему программированию, поэтому пока закросспостю в оба форума. Если что можно из одного удалить.



1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: GetCurrentProcessorNumber() под WinXP
От: Unmanaged Россия ICQ 476611995
Дата: 20.01.08 22:48
Оценка:
R>Как получить функциональность GetCurrentProcessorNumber()/NtGetCurrentProcessorNumber() под WinXP/2k?

Что мешает самому реализовать сию функцию через драйвер режима ядра?
STATUS_INVALID_DEVICE_REQUEST
Re[2]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 20.01.08 23:26
Оценка:
Здравствуйте, Unmanaged, Вы писали:

R>>Как получить функциональность GetCurrentProcessorNumber()/NtGetCurrentProcessorNumber() под WinXP/2k?


U>Что мешает самому реализовать сию функцию через драйвер режима ядра?


Я боюсь не уложиться в 100 тактов и без какой-либо сериализации
Это если будет вызов в ядро.

А можно ли "через драйвер" "добавить" поле в блок информации потока и класть в него номер процессора каждый раз при шедулинге? Это более интересный вопрос. В принципе так делать всё равно не входит в мои планы, но с познавательной т.з. очень интересный вопрос.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: GetCurrentProcessorNumber() под WinXP
От: Unmanaged Россия ICQ 476611995
Дата: 20.01.08 23:39
Оценка:
R>А можно ли "через драйвер" "добавить" поле в блок информации потока и класть в него номер процессора каждый раз при шедулинге?

Можно.
А ещё можно написать свою программно-аппаратную платформу, пересадить на неё половину человечества и не парится с отсутствием вызова NtGetCurrentProcessorNumber() на Windows < 5.2 .

R>В принципе так делать всё равно не входит в мои планы...


И правильно, ибо нех.
STATUS_INVALID_DEVICE_REQUEST
Re: GetCurrentProcessorNumber() под WinXP
От: Геннадий Майко США  
Дата: 21.01.08 06:23
Оценка: +2
Здравствуйте, remark, Вы писали:

R>Как получить функциональность GetCurrentProcessorNumber()/NtGetCurrentProcessorNumber() под WinXP/2k?

--
Зачем это нужно?

Не забывайте, что этот номер может изменится, как только Вы его получите. Это резко ограничивает полезность этой функиии.


R>В идеале хотелось чего-то вроде получения идентификатора текущего потока из блока информации потока.

--
А почему нельзя воспользоваться функциями типа GetCurrentThreadId() или ZwQuerySystemInformation() с нужным SYSTEM_INFORMATION_CLASS?

C уважением,
Геннадий Майко.
Re[2]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 21.01.08 09:49
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:

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


R>>Как получить функциональность GetCurrentProcessorNumber()/NtGetCurrentProcessorNumber() под WinXP/2k?

ГМ>--
ГМ>Зачем это нужно?

ГМ>Не забывайте, что этот номер может изменится, как только Вы его получите. Это резко ограничивает полезность этой функиии.


Сейчас отвечу там:
http://gzip.rsdn.ru/forum/message/2804333.1.aspx
Автор: remark
Дата: 20.01.08

(это то же но в форуме WinAPI)


R>>В идеале хотелось чего-то вроде получения идентификатора текущего потока из блока информации потока.

ГМ>--
ГМ>А почему нельзя воспользоваться функциями типа GetCurrentThreadId() или ZwQuerySystemInformation() с нужным SYSTEM_INFORMATION_CLASS?

Не вижу там нужной информации. Какой тип информации надо задавать и откуда это вытаскивать?


ГМ>C уважением,

ГМ>Геннадий Майко.

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: GetCurrentProcessorNumber() под WinXP
От: Геннадий Майко США  
Дата: 21.01.08 11:26
Оценка:
Здравствуйте, remark,

R>>>Как получить функциональность GetCurrentProcessorNumber()/NtGetCurrentProcessorNumber() под WinXP/2k?

ГМ>>--
ГМ>>Зачем это нужно?

ГМ>>Не забывайте, что этот номер может изменится, как только Вы его получите. Это резко ограничивает полезность этой функиии.


R>Сейчас отвечу там:

R>http://gzip.rsdn.ru/forum/message/2804333.1.aspx
Автор: remark
Дата: 20.01.08

--
Вспомните, что поток не может выполняться в одно и то же время на 2х или более CPU. Или, по другому, если поток выполняется, то он выполняется на одном, и только на одном, CPU. Отсюда, как мне кажется, вполне можно использовать для "контроля работы примитивов синхронизации, либо для оптимизации примитивов синхронизации" идентификатор именно потока, а не процессора.

C уважением,
Геннадий Майко.
Re[4]: GetCurrentProcessorNumber() под WinXP
От: Andrew.W Worobow https://github.com/Worobow
Дата: 21.01.08 11:34
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:

ГМ>Вспомните, что поток не может выполняться в одно и то же время на 2х или более CPU. Или, по другому, если поток выполняется, то он выполняется на одном, и только на одном, CPU. Отсюда, как мне кажется, вполне можно использовать для "контроля работы примитивов синхронизации, либо для оптимизации примитивов синхронизации" идентификатор именно потока, а не процессора.


Генадий, ребята немного перемудряют. На самом деле все просто есть SetThreadAffinityMask, сделал два потока установил для каждного привязку к процессору. И вот тебе и номер. А точнее нефиг думать про процессор номер.
Не все кто уехал, предал Россию.
Re[5]: GetCurrentProcessorNumber() под WinXP
От: Геннадий Майко США  
Дата: 21.01.08 11:54
Оценка:
Здравствуйте, Andrew.W Worobow,

ГМ>>Вспомните, что поток не может выполняться в одно и то же время на 2х или более CPU. Или, по другому, если поток выполняется, то он выполняется на одном, и только на одном, CPU. Отсюда, как мне кажется, вполне можно использовать для "контроля работы примитивов синхронизации, либо для оптимизации примитивов синхронизации" идентификатор именно потока, а не процессора.


AWW>Генадий, ребята немного перемудряют. На самом деле все просто есть SetThreadAffinityMask, сделал два потока установил для каждного привязку к процессору. И вот тебе и номер. А точнее нефиг думать про процессор номер.

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

C уважением,
Геннадий Майко.
Re[6]: GetCurrentProcessorNumber() под WinXP
От: Аноним  
Дата: 21.01.08 12:08
Оценка:
AWW>>Генадий, ребята немного перемудряют. На самом деле все просто есть SetThreadAffinityMask, сделал два потока установил для каждного привязку к процессору. И вот тебе и номер. А точнее нефиг думать про процессор номер.
ГМ>--
ГМ>Well, я, пока не знаю точно, что подразумевается под выделенным выше, но если это реализация, например, какого-то рекурсивного спинлока, то вполне можно обойтись и без номера процессора. Я вспоминаю, что эту же тему мы обсуждали как-то несколько лет назад с Евгением Музыченко в другом месте, и вроде пришли к этому же выводу.
Думаю это реализация хитропопого спинлока, который перед входом проверяет каким-либо образом, в каком состоянии находится текущий процессор (idle или выполняет какой то поток) и в зависимости от этого входит в спин или в ожидание в ядре.
Re[7]: GetCurrentProcessorNumber() под WinXP
От: Геннадий Майко США  
Дата: 21.01.08 12:24
Оценка:
А>Думаю это реализация хитропопого спинлока, который перед входом проверяет каким-либо образом, в каком состоянии находится текущий процессор (idle или выполняет какой то поток) и в зависимости от этого входит в спин или в ожидание в ядре.
--
Вряд ли это так. Потому что работающий на каком-то CPU код всегда выполняет именно "свой" поток и никогда не может выполнять какой-то другой поток, включая IDLE.

C уважением,
Геннадий Майко.
Re[8]: GetCurrentProcessorNumber() под WinXP
От: Аноним  
Дата: 21.01.08 12:37
Оценка:
А>>Думаю это реализация хитропопого спинлока, который перед входом проверяет каким-либо образом, в каком состоянии находится текущий процессор (idle или выполняет какой то поток) и в зависимости от этого входит в спин или в ожидание в ядре.
ГМ>--
ГМ>Вряд ли это так. Потому что работающий на каком-то CPU код всегда выполняет именно "свой" поток и никогда не может выполнять какой-то другой поток, включая IDLE.
Это понятно. Я про то что вообще можно считать что если все другие потоки находяится в ожидании в ядре или исполеяют код на других процессорах то можно крутить спин. Если же есть какой либо поток который в Ready тогда желательно уйти в ядро освободив проц. Вот только очень подозреваю что накладные расходы на все это перевесят обычную синхронизацию.
Re[9]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 21.01.08 17:29
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Если же есть какой либо поток который в Ready тогда желательно уйти в ядро освободив проц. Вот только очень подозреваю что накладные расходы на все это перевесят обычную синхронизацию.



Это делается с помощью SwitchToThread()/pthread_yield().
Нет, мне надо не для этого.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 21.01.08 17:32
Оценка:
Здравствуйте, Andrew.W Worobow, Вы писали:

AWW>Здравствуйте, Геннадий Майко, Вы писали:


ГМ>>Вспомните, что поток не может выполняться в одно и то же время на 2х или более CPU. Или, по другому, если поток выполняется, то он выполняется на одном, и только на одном, CPU. Отсюда, как мне кажется, вполне можно использовать для "контроля работы примитивов синхронизации, либо для оптимизации примитивов синхронизации" идентификатор именно потока, а не процессора.


AWW>Генадий, ребята немного перемудряют. На самом деле все просто есть SetThreadAffinityMask, сделал два потока установил для каждного привязку к процессору. И вот тебе и номер. А точнее нефиг думать про процессор номер.



SetThreadAffinityMask это палка о двух концах. Ей ты фактически выключаешь load balancing ОС, после чего load balancing надо делать вручную, что далеко не тривиальная задача. Ну ладно, допустим, в прикладном коде я могу это сделать. Но что делать, если ты работаешь на библиотечным кодом? Я не думаю, что кто-то будет использовать библиотеку, которая насильно делает привязку для всех пользовательских потоков.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: GetCurrentProcessorNumber() под WinXP
От: Andrew.W Worobow https://github.com/Worobow
Дата: 21.01.08 18:01
Оценка:
Здравствуйте, remark, Вы писали:

R>SetThreadAffinityMask это палка о двух концах. Ей ты фактически выключаешь load balancing ОС, после чего load balancing надо делать вручную, что далеко не тривиальная задача. Ну ладно, допустим, в прикладном коде я могу это сделать. Но что делать, если ты работаешь на библиотечным кодом? Я не думаю, что кто-то будет использовать библиотеку, которая насильно делает привязку для всех пользовательских потоков.


Хочешь load balancing, не лезь в процессоры.

Ты все равно вряд ли что-то сможешь улучшить. И вообще что ты хочешь сделать, не понятно? То номер процесора тебе в пользовательском режиме нужен. То LB. Определись.

Что ты хочешь улучшить, у тебя что загрузка процессора не 100% в вычислительных задачах, большие системные издержки? Где узкое место?
Не все кто уехал, предал Россию.
Re[7]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 21.01.08 22:52
Оценка:
Здравствуйте, Andrew.W Worobow, Вы писали:
Правила форума нарушены.
— оверквотинг
Правила можно найти в разделе FAQ данного форума и\или ресурса.
Нарушение правил может повлечь за собой санкции, описанные там же — модератор
AWW>Ты все равно вряд ли что-то сможешь улучшить. И вообще что ты хочешь сделать, не понятно? То номер процесора тебе в пользовательском режиме нужен. То LB. Определись.

О LB я упомянул только, что бы сказать, что нельзя вот так просто сделать SetThreadAffinityMask(), это компромисное решение. Помимо возможности определять номер процессора ты получишь ещё ряд артефактов, которые скорее всего ты не хочешь иметь. Больше никоим образом меня сейчас LB не интересует.

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 21.01.08 23:38
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:

ГМ>Вспомните, что поток не может выполняться в одно и то же время на 2х или более CPU. Или, по другому, если поток выполняется, то он выполняется на одном, и только на одном, CPU. Отсюда, как мне кажется, вполне можно использовать для "контроля работы примитивов синхронизации, либо для оптимизации примитивов синхронизации" идентификатор именно потока, а не процессора.


Иногда можно, иногда нужен именно номер процессора.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 22.01.08 01:07
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:

ГМ>Well, я, пока не знаю точно, что подразумевается под выделенным выше, но если это реализация, например, какого-то рекурсивного спинлока, то вполне можно обойтись и без номера процессора. Я вспоминаю, что эту же тему мы обсуждали как-то несколько лет назад с Евгением Музыченко в другом месте, и вроде пришли к этому же выводу.


Здесь я написал более подробно, что я имею в виду:
http://gzip.rsdn.ru/forum/message/2806303.1.aspx
Автор: remark
Дата: 22.01.08

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


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: GetCurrentProcessorNumber() под WinXP
От: Геннадий Майко США  
Дата: 22.01.08 08:16
Оценка:
Здравствуйте, remark,

R>Здесь я написал более подробно, что я имею в виду:

R>http://gzip.rsdn.ru/forum/message/2806303.1.aspx
Автор: remark
Дата: 22.01.08

R>Так же описал, почему в общем случае нельзя обойтись без номера процессора, ну точнее можно, но с ним существенно лучше.
--
В примере Вы сравниваете апельсины с яблоками, потому что результаты работы 2х функций разные. Делать какие-то далеко идущие выводы из этого, на мой взгляд, опасно. Поэтому было бы интересно посмотреть на результаты корректного сравнения, пусть даже и на надуманном примере.

Если я правильно понял, Вы хотите поместить некоторые данные в кеш процессора и работать только с ними "локально" в этом кэше, нет?

C уважением,
Геннадий Майко.
Re[8]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 22.01.08 17:40
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:

ГМ>Здравствуйте, remark,


R>>Здесь я написал более подробно, что я имею в виду:

R>>http://gzip.rsdn.ru/forum/message/2806303.1.aspx
Автор: remark
Дата: 22.01.08

R>>Так же описал, почему в общем случае нельзя обойтись без номера процессора, ну точнее можно, но с ним существенно лучше.
ГМ>--
ГМ>В примере Вы сравниваете апельсины с яблоками, потому что результаты работы 2х функций разные.

Естественно, 2 разные функции делают разное. Я сравниваю 2 разных метода решения одной и той же задачи. По-моему, тут всё корректно. А сравнивать 2 функции, которые дают одинаковый результат имхо бессмысленно...


ГМ>Делать какие-то далеко идущие выводы из этого, на мой взгляд, опасно. Поэтому было бы интересно посмотреть на результаты корректного сравнения, пусть даже и на надуманном примере.


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


ГМ>Если я правильно понял, Вы хотите поместить некоторые данные в кеш процессора и работать только с ними "локально" в этом кэше, нет?


Ну, так скажем, примерно. Совсем локально — это уже другой случай, тогда можно просто размещать данные на стеке. Я же хочу "большую часть времени" работать с данными уже находящимися в кэше процессора, но при этом иметь возможность и агрегировать эти данные.
Т.е. с логической т.з. мне нужны глобальные данные, но с физической т.з. я хочу сделать их локальными.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: GetCurrentProcessorNumber() под WinXP
От: Sergey Storozhevykh Россия  
Дата: 23.01.08 06:56
Оценка:
Здравствуйте, remark, Вы писали:

R>О LB я упомянул только, что бы сказать, что нельзя вот так просто сделать SetThreadAffinityMask(), это компромисное решение. Помимо возможности определять номер процессора ты получишь ещё ряд артефактов, которые скорее всего ты не хочешь иметь. Больше никоим образом меня сейчас LB не интересует.


Можно более мягко попросить планировщик выбирать предпочитаемый процессор для исполнения кода потока — SetThreadIdealProcessor. Для ваших целей оптимизации чего-то там вполне может подойти

When a thread becomes ready to run, Windows 2000 first tries to schedule the thread to run on an idle processor. If there is a choice of idle processors, preference is given first to the thread's ideal processor, then to the thread's last processor, and then to the currently executing processor (that is, the CPU on which the scheduling code is running). If none of these CPUs are idle, Windows 2000 picks the first available idle processor by scanning the idle processor mask from highest to lowest CPU number.

If all processors are currently busy and a thread becomes ready, Windows 2000 looks to see whether it can preempt a thread in the running or standby state on one of the CPUs. Which CPU is examined? The first choice is the thread's ideal processor, and the second choice is the thread's last processor. If neither of those CPUs are in the thread's affinity mask, Windows 2000 selects the highest processor in the active processor mask that the thread can run on.

Re[9]: GetCurrentProcessorNumber() под WinXP
От: Геннадий Майко США  
Дата: 23.01.08 08:54
Оценка:
Здравствуйте, remark,

R>>>Здесь я написал более подробно, что я имею в виду:

R>>>http://gzip.rsdn.ru/forum/message/2806303.1.aspx
Автор: remark
Дата: 22.01.08

ГМ>>--
ГМ>>В примере Вы сравниваете апельсины с яблоками, потому что результаты работы 2х функций разные.

R>Естественно, 2 разные функции делают разное. Я сравниваю 2 разных метода решения одной и той же задачи. По-моему, тут всё корректно. А сравнивать 2 функции, которые дают одинаковый результат имхо бессмысленно...

--
1. Ваши два разных метода решения одной и той же задачи приводят к разным ответам, поэтому я по прежнему считаю Ваши результаты сравнения некорректными.
2. Почему же бессмысленно сравнивать 2 функции (устройства, методы и т.п.), которые дают один результат? Этот результат-то можно получить разными способами, за разное времы, с различными усилями и т.п.


ГМ>>Если я правильно понял, Вы хотите поместить некоторые данные в кеш процессора и работать только с ними "локально" в этом кэше, нет?


R>Ну, так скажем, примерно. Совсем локально — это уже другой случай, тогда можно просто размещать данные на стеке. Я же хочу "большую часть времени" работать с данными уже находящимися в кэше процессора, но при этом иметь возможность и агрегировать эти данные.

R>Т.е. с логической т.з. мне нужны глобальные данные, но с физической т.з. я хочу сделать их локальными.
--
1. Что такое "агрегировать эти данные"?

2. Как только Вы захотите корректно использовать глобальные данные, Вам нужно будет обеспечить механизм их консистентной и корректной видимости для всех CPU, которые захотят их использовать. Вам обязательно понадобится механизм обновления или переноса измененного глобального значения этой переменной от одного CPU к другому. Я бы попытался сравнивать время работу именно этих механизмов, хотя боюсь, это будет не просто. Более того, я бы стал это делать только тогда, когда выяснилось бы, что именно это является bottleneck в моей задаче.

С уважением,
Геннадий Майко.
Re[9]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 23.01.08 10:59
Оценка:
Здравствуйте, Sergey Storozhevykh, Вы писали:

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


R>>О LB я упомянул только, что бы сказать, что нельзя вот так просто сделать SetThreadAffinityMask(), это компромисное решение. Помимо возможности определять номер процессора ты получишь ещё ряд артефактов, которые скорее всего ты не хочешь иметь. Больше никоим образом меня сейчас LB не интересует.


SS>Можно более мягко попросить планировщик выбирать предпочитаемый процессор для исполнения кода потока — SetThreadIdealProcessor. Для ваших целей оптимизации чего-то там вполне может подойти



Речь идёт о библиотечном коде, т.ч. никакие трюки типа SetThreadIdealProcessor() и SetThreadAffinityMask() не подходят.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 23.01.08 11:11
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:

ГМ>Здравствуйте, remark,


R>>>>Здесь я написал более подробно, что я имею в виду:

R>>>>http://gzip.rsdn.ru/forum/message/2806303.1.aspx
Автор: remark
Дата: 22.01.08

ГМ>>>--
ГМ>>>В примере Вы сравниваете апельсины с яблоками, потому что результаты работы 2х функций разные.

R>>Естественно, 2 разные функции делают разное. Я сравниваю 2 разных метода решения одной и той же задачи. По-моему, тут всё корректно. А сравнивать 2 функции, которые дают одинаковый результат имхо бессмысленно...

ГМ>--
ГМ>1. Ваши два разных метода решения одной и той же задачи приводят к разным ответам, поэтому я по прежнему считаю Ваши результаты сравнения некорректными.
ГМ>2. Почему же бессмысленно сравнивать 2 функции (устройства, методы и т.п.), которые дают один результат? Этот результат-то можно получить разными способами, за разное времы, с различными усилями и т.п.


Если под разным результатами ты имеешь в виду, что в одном случае сумма лежит в одной переменной, а в другом в нескольких, то это не есть разный результат, т.к. я в тест специально включил и агрегирование данных. В одном случае оно выглядит как:
            volatile int x = values[0].value;


В другом как:
            volatile int x = 0;
            for (int j = 0; j != arch::processor_count; ++j)
            {
                x += values[j].value;
            }


Т.ч. в этом смысле результата разного нет — я всегда получаю полную сумму.




ГМ>>>Если я правильно понял, Вы хотите поместить некоторые данные в кеш процессора и работать только с ними "локально" в этом кэше, нет?


R>>Ну, так скажем, примерно. Совсем локально — это уже другой случай, тогда можно просто размещать данные на стеке. Я же хочу "большую часть времени" работать с данными уже находящимися в кэше процессора, но при этом иметь возможность и агрегировать эти данные.

R>>Т.е. с логической т.з. мне нужны глобальные данные, но с физической т.з. я хочу сделать их локальными.
ГМ>--
ГМ>1. Что такое "агрегировать эти данные"?

Это то, что я привёл выше.


ГМ>2. Как только Вы захотите корректно использовать глобальные данные, Вам нужно будет обеспечить механизм их консистентной и корректной видимости для всех CPU, которые захотят их использовать.


В тесте это обеспечивается.


ГМ>Вам обязательно понадобится механизм обновления или переноса измененного глобального значения этой переменной от одного CPU к другому.


У меня все компьютеры с когерентрым кэшем. Компьютеры с некогерентным кэшем меня пока не интересует... потому что я их не видел.


ГМ>Я бы попытался сравнивать время работу именно этих механизмов, хотя боюсь, это будет не просто.


Всё, что нужно, учитывается в тесте. Это полноценный вариант счётчика.


ГМ>Более того, я бы стал это делать только тогда, когда выяснилось бы, что именно это является bottleneck в моей задаче.


Я отказываюсь это обсуждать — с этим в Философию.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: GetCurrentProcessorNumber() под WinXP
От: Геннадий Майко США  
Дата: 23.01.08 12:36
Оценка:
Здравствуйте, remark,

R>Если под разным результатами ты имеешь в виду, что в одном случае сумма лежит в одной переменной, а в другом в нескольких, то это не есть разный результат, т.к. я в тест специально включил и агрегирование данных. В одном случае оно выглядит как:

R>
R>            volatile int x = values[0].value;
R>


R>В другом как:

R>
R>            volatile int x = 0;
R>            for (int j = 0; j != arch::processor_count; ++j)
R>            {
R>                x += values[j].value;
R>            }
R>


R>Т.ч. в этом смысле результата разного нет — я всегда получаю полную сумму.

--
Замените arch::processor_count на случайную величину, и я сомневаюсь, что результаты такого теста будут сильно отличаться от Вашего оригинального.


ГМ>>Вам обязательно понадобится механизм обновления или переноса измененного глобального значения этой переменной от одного CPU к другому.


R>У меня все компьютеры с когерентрым кэшем. Компьютеры с некогерентным кэшем меня пока не интересует... потому что я их не видел.


ГМ>>Я бы попытался сравнивать время работу именно этих механизмов, хотя боюсь, это будет не просто.


R>Всё, что нужно, учитывается в тесте. Это полноценный вариант счётчика.

--
Да, я тоже имею в виду компьютеры с когерентым кешем. Я просто хочу Вам подсказать, что вариантов обеспечения такой когерентности может быть не один. Посмотрите, например, описания тех же x86 процессоров.



ГМ>>Более того, я бы стал это делать только тогда, когда выяснилось бы, что именно это является bottleneck в моей задаче.


R>Я отказываюсь это обсуждать — с этим в Философию.

--
Да, наверное, на этом стоит прекратить нашу дискуссию.

С уважением,
Геннадий Майко.
Re[12]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 23.01.08 12:41
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:

R>>Т.ч. в этом смысле результата разного нет — я всегда получаю полную сумму.

ГМ>--
ГМ>Замените arch::processor_count на случайную величину, и я сомневаюсь, что результаты такого теста будут сильно отличаться от Вашего оригинального.

Какой в этом смысл?
Эта величина не должна быть случайной!



R>>Всё, что нужно, учитывается в тесте. Это полноценный вариант счётчика.

ГМ>--
ГМ>Да, я тоже имею в виду компьютеры с когерентым кешем. Я просто хочу Вам подсказать, что вариантов обеспечения такой когерентности может быть не один. Посмотрите, например, описания тех же x86 процессоров.

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



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[13]: GetCurrentProcessorNumber() под WinXP
От: Геннадий Майко США  
Дата: 23.01.08 13:21
Оценка:
Здравствуйте, remark,

R>>>Т.ч. в этом смысле результата разного нет — я всегда получаю полную сумму.

ГМ>>--
ГМ>>Замените arch::processor_count на случайную величину, и я сомневаюсь, что результаты такого теста будут сильно отличаться от Вашего оригинального.

R>Какой в этом смысл?

R>Эта величина не должна быть случайной!
--
Смысл простой — предпочтительно работать с разными переменными в разных потоках.
А какая разница — случайная ли она из-за вызова функции GetCurrentProcessorNumber() или или из-за вызова функции rand()?


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

С уважением,
Геннадий Майко.
Re[14]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 23.01.08 15:03
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:

Правила форума нарушены.
— оверквотинг
Правила можно найти в разделе FAQ данного форума и\или ресурса.
Нарушение правил может повлечь за собой санкции, описанные там же — модератор
ГМ>Если Ваша цель — как-то разделить обработку переменной, то это можно делать не только по номеру процессора, но и по любому другому закону; главное, чтобы обеспечивалось уникальность номера для каждого потока команд.


Здесь я описал почему не всегда можно использовать идентификатор потока:
http://www.rsdn.ru/Forum/message/2808741.aspx
Автор: Andrew.W Worobow
Дата: 23.01.08


Случайный номер имхо это заведомо хуже, чем номер процессора.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: GetCurrentProcessorNumber() под WinXP
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 28.01.08 17:47
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:

ГМ>Well, я, пока не знаю точно, что подразумевается под выделенным выше, но если это реализация, например, какого-то рекурсивного спинлока, то вполне можно обойтись и без номера процессора. Я вспоминаю, что эту же тему мы обсуждали как-то несколько лет назад с Евгением Музыченко в другом месте, и вроде пришли к этому же выводу.


Да, я тогда заменил KeGetCurrentProcessorNumber на KeGetCurrentThread, и не только получил всю нужную функциональность, но и избавился от лишних проверок, ибо номер процессора может меняться, а идентификатор потока — нет.

Только вот возникает ощущение, что рекурсивные спинлоки — штука удобная и универсальная, но провоцирует на избыточный код, и порой довольно заметно снижает быстродействие
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 28.01.08 18:06
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Геннадий Майко, Вы писали:


ГМ>>Well, я, пока не знаю точно, что подразумевается под выделенным выше, но если это реализация, например, какого-то рекурсивного спинлока, то вполне можно обойтись и без номера процессора. Я вспоминаю, что эту же тему мы обсуждали как-то несколько лет назад с Евгением Музыченко в другом месте, и вроде пришли к этому же выводу.


ЕМ>Да, я тогда заменил KeGetCurrentProcessorNumber на KeGetCurrentThread, и не только получил всю нужную функциональность, но и избавился от лишних проверок, ибо номер процессора может меняться, а идентификатор потока — нет.



Это значит, что функциональность, которая тебе требовалась, прямолинейнее той, которая требуется мне. Про то, что можно использовать идентификатор потока, я, естественно, в курсе. Про то, что его не всегда достаточно я писал здесь:
http://gzip.rsdn.ru/forum/message/2806303.1.aspx
Автор: remark
Дата: 22.01.08



ЕМ>Только вот возникает ощущение, что рекурсивные спинлоки — штука удобная и универсальная, но провоцирует на избыточный код, и порой довольно заметно снижает быстродействие



Хммм, вообще считается, что рекурсивные локи — вещь вредная, т.к. провоцирует на небрежный/кривой код. В любом случае, они тривиально реализуются с помощью GetСurrentThreadId(), идентификатор процессора тут совершенно не нужен.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: GetCurrentProcessorNumber() под WinXP
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.01.08 05:11
Оценка:
Здравствуйте, remark, Вы писали:

R>Это значит, что функциональность, которая тебе требовалась, прямолинейнее той, которая требуется мне. Про то, что можно использовать идентификатор потока, я, естественно, в курсе. Про то, что его не всегда достаточно я писал здесь:

R>http://gzip.rsdn.ru/forum/message/2806303.1.aspx
Автор: remark
Дата: 22.01.08


Я, честно говоря, так и не понял, чего ты хочешь достичь — практически, а не теоретически. Любопытства ради я прогнал твой пример на двухъядерном Athlon 64 X2, под виндами (линуха у меня нет). Создавал восемь потоков с привязкой к процессорам и без нее. Скомпилировано MS VS 2005 (VC 8), _InterlockedIncrement раскрывается в lock xadd. Ну и во втором случае _InterlockedIncrement будет избыточным, ибо конкуренции за переменную нет.

Получилось вот что (количество тактов на проход цикла):

1 с привязкой к процессорам — 56
1 без привязки — 57
2 с привязкой с _InterlockedIncrement — 12
2 без привязки с _InterlockedIncrement — 12
2 с привязкой с ++ — 5
2 без привязки с ++ — 6

То есть, наиболее эффективный вариант — привязывать потоки к процессорам. Если каждый поток занимается интенсивной вычислительной работой, то от привязки к разным процессорам они только выиграют. Если же загрузка неравномерная, то и вероятность конфликта за переменную падает многократно, а вероятность получения номера на одном процессоре и последующего переключения на другой, наоборот, возрастает. Так что обоснованность твоего стремления представляется весьма сомнительной.

Если есть практические примеры, показывающие эффективность именно выбранного тобой подхода — буду рад посмотреть.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: GetCurrentProcessorNumber() под WinXP
От: MShura  
Дата: 29.01.08 07:48
Оценка:
ЕМ>Я, честно говоря, так и не понял, чего ты хочешь достичь — практически, а не теоретически.

По-моему товарищ remark хочет использовать/повторить идею, которая реализована в windows и linux при подсчете статистики обращений к диску/тому.
Так, если посмотреть на реализацию FAT, то можно увидеть, что драйвер создает столько экземпляров FILE_SYSTEM_STATISTICS, сколько процессоров и во время работы заполняет их так:

#define CollectCreateHitStatistics(VCB) {                                                \
    PFILE_SYSTEM_STATISTICS Stats = &(VCB)->Statistics[KeGetCurrentProcessorNumber()];   \
    Stats->Fat.CreateHits += 1;                                                          \
}

#define CollectCreateStatistics(VCB,STATUS) {                                            \
    PFILE_SYSTEM_STATISTICS Stats = &(VCB)->Statistics[KeGetCurrentProcessorNumber()];   \
    if ((STATUS) == STATUS_SUCCESS) {                                                    \
        Stats->Fat.SuccessfulCreates += 1;                                               \
    } else {                                                                             \
        Stats->Fat.FailedCreates += 1;                                                   \
    }                                                                                    \
}


При запросе FSCTL_FILESYSTEM_GET_STATISTICS драйвер не делает никаких сложений, а просто копирует все структуры в выходной буффер, оставляя сложение нужных полей на откуп вызывающему коду.

Похожий подход и в linux (include/linux/genhd.h):
struct gendisk {
....
#ifdef    CONFIG_SMP
    struct disk_stats *dkstats;
#else
    struct disk_stats dkstats;
#endif
};

#ifdef    CONFIG_SMP
// Обновление статистики
#define disk_stat_add(gendiskp, field, addnd)            \
    do {                            \
        preempt_disable();                \
        // Макрос __disk_stat_add раскрыт               \
        per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd;\
        preempt_enable();                \
    } while (0)

// Чтение итоговой статистики, например для вывода в файл /sys/block/<dev>/stat
#define disk_stat_read(gendiskp, field)                    \
({                                    \
    typeof(gendiskp->dkstats->field) res = 0;            \
    int i;                                \
    for_each_possible_cpu(i)                    \
        res += per_cpu_ptr(gendiskp->dkstats, i)->field;    \
    res;                                \
})
#endif
Re[10]: GetCurrentProcessorNumber() под WinXP
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.01.08 08:18
Оценка:
Здравствуйте, MShura, Вы писали:

MS>идею, которая реализована в windows и linux при подсчете статистики обращений к диску/тому.

MS>Так, если посмотреть на реализацию FAT, то можно увидеть, что драйвер создает столько экземпляров FILE_SYSTEM_STATISTICS

Э-э-э... А какой-нибудь объективный смысл в таком подходе есть, или это сугубо произвольная фантазия разработчиков? О чем может говорить статистика обращений того или иного процессора к дискам, и какую практическую пользу можно из нее извлечь?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[10]: GetCurrentProcessorNumber() под WinXP
От: Геннадий Майко США  
Дата: 29.01.08 08:36
Оценка:
Здравствуйте, MShura,

MS>По-моему товарищ remark хочет использовать/повторить идею, которая реализована в windows и linux при подсчете статистики обращений к диску/тому.


MS>[/ccode]

MS>#ifdef CONFIG_SMP
MS>// Обновление статистики
MS>#define disk_stat_add(gendiskp, field, addnd) \
MS> do { \
MS> preempt_disable(); \
MS> // Макрос __disk_stat_add раскрыт \
MS> per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd;\
MS> preempt_enable(); \
MS> } while (0)
MS>[/ccode]
--
Кстати, я не знаю, как там в Windows, но в linux использование идентификатора процессора делается достаточно корректно, так как на момент изменения переменной запрещается смена процессора.

C уважением,
Геннадий Майко.
Re[11]: GetCurrentProcessorNumber() под WinXP
От: MShura  
Дата: 29.01.08 09:22
Оценка:
MS>>идею, которая реализована в windows и linux при подсчете статистики обращений к диску/тому.
MS>>Так, если посмотреть на реализацию FAT, то можно увидеть, что драйвер создает столько экземпляров FILE_SYSTEM_STATISTICS

ЕМ>Э-э-э... А какой-нибудь объективный смысл в таком подходе есть, или это сугубо произвольная фантазия разработчиков? О чем может говорить статистика обращений того или иного процессора к дискам, и какую практическую пользу можно из нее извлечь?


Даже не могу сказать про практическую пользу знаний статистики по отдельным процессорам, к тому-же в конкретной файловой системе, но в сумме смысл уже есть.
Так в windows task manager может показывать статистику обращений к диску (не к тому).

В linux можно из этих знаний даже извлечь практическую пользу:
Так в файле /sys/block/<dev>/stat выводится следующая статистика по диску на текущий момент:

Name            units         description
----            -----         -----------
read I/Os       requests      number of read I/Os processed
read merges     requests      number of read I/Os merged with in-queue I/O
read sectors    sectors       number of sectors read
read ticks      milliseconds  total wait time for read requests
write I/Os      requests      number of write I/Os processed
write merges    requests      number of write I/Os merged with in-queue I/O
write sectors   sectors       number of sectors written
write ticks     milliseconds  total wait time for write requests
in_flight       requests      number of I/Os currently in flight
io_ticks        milliseconds  total time this block device has been active
time_in_queue   milliseconds  total wait time for all requests


Поскольку планировщик ввода-вывода (elevator) в linux можно менять на лету, а также менять его параметры, то можно быстро (без перегрузок) оценивать эффективность того или иного элеватора на конкретных файловых операциях или на том или ином сценарии действий или на том или ином носителе.
Справедливости ради стоит сказать, что я не увидел особой разницы в элеваторах deadline/noop/as в обычных условиях на embedded устройствах.
А проводить сложные эксперименты/измерения ради интереса было лень.
Re[11]: GetCurrentProcessorNumber() под WinXP
От: MShura  
Дата: 29.01.08 09:33
Оценка:
ГМ>Кстати, я не знаю, как там в Windows, но в linux использование идентификатора процессора делается достаточно корректно, так как на момент изменения переменной запрещается смена процессора.

Макросы CollectCreateHitStatistics/CollectCreateStatistics
вызываются внутри блока FsRtlEnterFileSystem/FsRtlExitFileSystem
Re[9]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 11:24
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


R>>Это значит, что функциональность, которая тебе требовалась, прямолинейнее той, которая требуется мне. Про то, что можно использовать идентификатор потока, я, естественно, в курсе. Про то, что его не всегда достаточно я писал здесь:

R>>http://gzip.rsdn.ru/forum/message/2806303.1.aspx
Автор: remark
Дата: 22.01.08


ЕМ>Я, честно говоря, так и не понял, чего ты хочешь достичь — практически, а не теоретически. Любопытства ради я прогнал твой пример на двухъядерном Athlon 64 X2, под виндами (линуха у меня нет). Создавал восемь потоков с привязкой к процессорам и без нее. Скомпилировано MS VS 2005 (VC 8), _InterlockedIncrement раскрывается в lock xadd. Ну и во втором случае _InterlockedIncrement будет избыточным, ибо конкуренции за переменную нет.


Во-втором случае _InterlockedIncrement *не* избыточный, т.к. номер процессора может измениться, это не более, чем хинт. По крайней мере в user-space. _InterlockedIncrement избыточный только в случае жёсткой привязки потоков к процессорам.


ЕМ>Получилось вот что (количество тактов на проход цикла):


ЕМ>1 с привязкой к процессорам — 56

ЕМ>1 без привязки — 57
ЕМ>2 с привязкой с _InterlockedIncrement — 12
ЕМ>2 без привязки с _InterlockedIncrement — 12
ЕМ>2 с привязкой с ++ — 5
ЕМ>2 без привязки с ++ — 6


ЕМ>То есть, наиболее эффективный вариант — привязывать потоки к процессорам. Если каждый поток занимается интенсивной вычислительной работой, то от привязки к разным процессорам они только выиграют. Если же загрузка неравномерная, то и вероятность конфликта за переменную падает многократно, а вероятность получения номера на одном процессоре и последующего переключения на другой, наоборот, возрастает. Так что обоснованность твоего стремления представляется весьма сомнительной.


Про то, что привязка не всегда возможно я уже писал и писал причины. Допустим ты делаешь библиотечный код. НУ НЕ МОЖЕШЬ ТЫ ПРИВЯЗЫВАТЬ ПОЛЬЗОВАТЕЛЬСКИЕ ПОТОКИ К ПРОЦЕССОРАМ. НЕ МОЖЕШЬ!!!

Учитывая 2, указанные мной причины, получаем:

ЕМ>1 без привязки — 57

ЕМ>2 без привязки с _InterlockedIncrement — 12

Я вижу, что эти 2 цифры различаются в 4,75 раза. Что отсюда не очевидно? И дело не только голой производительности, более серьёзно дело обстоит с масштабируемостью. Если провести более исчерпывающее тестирование, то ты можешь получить следующие цифры масштабируемости.

Умная, аккуратная синхронизация, уважающая кэш:
1 ядро — 1
2 ядра — 2
2 процессора — 2
2 процессора по 2 ядра — 4

Тупая синхронизация в лоб:
1 ядро — 1
2 ядра — 0.6
2 процессора — 0.4
2 процессора по 2 ядра — 0.2

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


ЕМ>Если есть практические примеры, показывающие эффективность именно выбранного тобой подхода — буду рад посмотреть.


Конкретные алгоритмы я не могу сейчас раскрывать. Но множество примеров можно поглядеть в ядрах ОС, где "копия на процессора" используется достаточно часто. Это могут быть различные мьютексы, сбор статистики, техники типа RCU. Пару примеров привёл MShura.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 11:25
Оценка:
Здравствуйте, MShura, Вы писали:

ЕМ>>Я, честно говоря, так и не понял, чего ты хочешь достичь — практически, а не теоретически.


MS>По-моему товарищ remark хочет использовать/повторить идею, которая реализована в windows и linux при подсчете статистики обращений к диску/тому.



В частности и это можно повторить. Только в user-space всё равно надо использовать Interlocked операции.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 11:28
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


MS>>идею, которая реализована в windows и linux при подсчете статистики обращений к диску/тому.

MS>>Так, если посмотреть на реализацию FAT, то можно увидеть, что драйвер создает столько экземпляров FILE_SYSTEM_STATISTICS

ЕМ>Э-э-э... А какой-нибудь объективный смысл в таком подходе есть, или это сугубо произвольная фантазия разработчиков? О чем может говорить статистика обращений того или иного процессора к дискам, и какую практическую пользу можно из нее извлечь?



Я думаю, что используется статистика только после сложения. Раздельный подсчёт — это не более чем деталь реализации.
Практическая польза следующая — получить линейно масштабируемую систему, в отличие от линейно деградирующей системы. Для меня это достаточное условие.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: GetCurrentProcessorNumber() под WinXP
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.01.08 11:48
Оценка:
Здравствуйте, remark, Вы писали:

R>Допустим ты делаешь библиотечный код. НУ НЕ МОЖЕШЬ ТЫ ПРИВЯЗЫВАТЬ ПОЛЬЗОВАТЕЛЬСКИЕ ПОТОКИ К ПРОЦЕССОРАМ. НЕ МОЖЕШЬ!!!


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

R>Я вижу, что эти 2 цифры различаются в 4,75 раза. Что отсюда не очевидно?


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

ЕМ>>Если есть практические примеры, показывающие эффективность именно выбранного тобой подхода — буду рад посмотреть.


R>Конкретные алгоритмы я не могу сейчас раскрывать.


Начинается... Каким бы новаторским и секретным ни был алгоритм — нет проблем его переиначить или с ходу придумать аналогию, годную для примера.

R> Но множество примеров можно поглядеть в ядрах ОС, где "копия на процессора" используется достаточно часто. Это могут быть различные мьютексы, сбор статистики, техники типа RCU. Пару примеров привёл MShura.


В ядрах ОС понятие "номер процессора" имеет вполне конкретное значение, в отличие от user-mode. Оттого и не возникало реальной необходимости в функции GetCurrentProcessorNumber.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[12]: GetCurrentProcessorNumber() под WinXP
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.01.08 11:48
Оценка:
Здравствуйте, remark, Вы писали:

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


Ты хочешь сказать, что конкуренция за разделяемый счетчик обращений ко внешнему устройству способна внести хоть сколько-то заметный вклад во время обработки запроса? Я бы вес этой конкуренции во всей обработке оценил где-нибудь в сотые-тысячные доли процента, а то и меньше.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[11]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 13:29
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

R>>Допустим ты делаешь библиотечный код. НУ НЕ МОЖЕШЬ ТЫ ПРИВЯЗЫВАТЬ ПОЛЬЗОВАТЕЛЬСКИЕ ПОТОКИ К ПРОЦЕССОРАМ. НЕ МОЖЕШЬ!!!


ЕМ>А если спокойно подумать? Что за библиотечный код, который, не зная о процессорах и потоках, тем не менее претендует на предельно высокое быстродействие? Это извращение, а не код. Либо библиотека сама создает потоки по определенной схеме, либо требует этого от кода, ее использующего. Либо, соответственно, ничего этого не делает, и на эффективность не претендует.



Ну ладно, вот конкретный пример. WinAPI. CRITICAL_SECTION трогать не будем, но вот в Vista появилось новое API — SRWLock (см. InitializeSRWLock()). Т.е. ты считаешь нормальным, если бы в документации было написано, что все потоки, которые вызывают AcquireSRWLockExclusive()/AcquireSRWLockShared() должны быть строго привязаны к процессорам, иначе пользоваться этой функциональностью запрещено? Или ты считаешь, что от таких примитивов не требуется быстродействия и масштабируемости?



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 13:33
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

R>>Я вижу, что эти 2 цифры различаются в 4,75 раза. Что отсюда не очевидно?


ЕМ>Отсюда не очевидно, зачем нужно применять на практике этот странный вариант, когда банальное распределение по процессорам дает выигрыш еще в два раза.



Заметь, что делая жёсткую привязку потоков к процессорам ты фактически говоришь ОС "Пожалуйста, не делай load-balancing для меня, я полностью беру этот сложный и нетривиальный вопрос на себя". Имхо, это ещё более не похоже на решение для "общего случая". Совсем не похоже.
Если ты не решишь хорошо вопрос load-balancing'а, то этот "банальный" вариант даст тебе не выигрыш в 2 раза, а проигрыш в N раз.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 13:38
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:


ЕМ>>>Если есть практические примеры, показывающие эффективность именно выбранного тобой подхода — буду рад посмотреть.


R>>Конкретные алгоритмы я не могу сейчас раскрывать.


ЕМ>Начинается... Каким бы новаторским и секретным ни был алгоритм — нет проблем его переиначить или с ходу придумать аналогию, годную для примера.



Ну ладно, хорошо. Вот набросок алгоритма масштабируемого rw-mutex'а.
По флагу на процессор. При доступе на чтение каждый поток захватывает флаг на "текущем" процессоре с помощью Interlocked операции. При доступе на чтение поток последовательно захватывает все флаги.

Ты не можешь сделать аналогичный алгоритм без:
1. требования привязки потоков к процессорам (что совершенно неприемлемо в общем случае)
или
2. требования предварительной регистрации/разрегистрации всех пользовательских потоков, и увеличения стоимости захвата на запись пропорционально кол-ву пользовательских потоков



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[13]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 13:39
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


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


ЕМ>Ты хочешь сказать, что конкуренция за разделяемый счетчик обращений ко внешнему устройству способна внести хоть сколько-то заметный вклад во время обработки запроса? Я бы вес этой конкуренции во всей обработке оценил где-нибудь в сотые-тысячные доли процента, а то и меньше.



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



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: GetCurrentProcessorNumber() под WinXP
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.01.08 13:54
Оценка:
Здравствуйте, remark, Вы писали:

R>в Vista появилось новое API — SRWLock (см. InitializeSRWLock()). Т.е. ты считаешь нормальным, если бы в документации было написано, что все потоки, которые вызывают AcquireSRWLockExclusive()/AcquireSRWLockShared() должны быть строго привязаны к процессорам, иначе пользоваться этой функциональностью запрещено? Или ты считаешь, что от таких примитивов не требуется быстродействия и масштабируемости?


Я считаю, применение примитивов синхронизации, равно как и всех остальных средств API, следует привязывать к алгоритму, особенностям кода, особенностям обрабатываемых данных и так далее. А не придумывать единый универсальный механизм всех времен и народов, который одновременно будет еще и неимоверно эффективен.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[13]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 14:11
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


R>>в Vista появилось новое API — SRWLock (см. InitializeSRWLock()). Т.е. ты считаешь нормальным, если бы в документации было написано, что все потоки, которые вызывают AcquireSRWLockExclusive()/AcquireSRWLockShared() должны быть строго привязаны к процессорам, иначе пользоваться этой функциональностью запрещено? Или ты считаешь, что от таких примитивов не требуется быстродействия и масштабируемости?


ЕМ>Я считаю, применение примитивов синхронизации, равно как и всех остальных средств API, следует привязывать к алгоритму, особенностям кода, особенностям обрабатываемых данных и так далее. А не придумывать единый универсальный механизм всех времен и народов, который одновременно будет еще и неимоверно эффективен.



Полностью согласен. Но в значительном проценте случаев твой выбор падёт на мьютес или rw мьютекс. Ты требовал от меня конкретики. Хорошо, давай говорить о rw-мьютексе. Так что? Мьютекс должен требовать привязки всех пользовательских потоков? Или быть не масштабируемым?



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[13]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 14:13
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


R>>в Vista появилось новое API — SRWLock (см. InitializeSRWLock()). Т.е. ты считаешь нормальным, если бы в документации было написано, что все потоки, которые вызывают AcquireSRWLockExclusive()/AcquireSRWLockShared() должны быть строго привязаны к процессорам, иначе пользоваться этой функциональностью запрещено? Или ты считаешь, что от таких примитивов не требуется быстродействия и масштабируемости?


ЕМ>Я считаю, применение примитивов синхронизации, равно как и всех остальных средств API, следует привязывать к алгоритму, особенностям кода, особенностям обрабатываемых данных и так далее. А не придумывать единый универсальный механизм всех времен и народов, который одновременно будет еще и неимоверно эффективен.



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



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: GetCurrentProcessorNumber() под WinXP
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.01.08 14:18
Оценка:
Здравствуйте, remark, Вы писали:

R>Заметь, что делая жёсткую привязку потоков к процессорам ты фактически говоришь ОС "Пожалуйста, не делай load-balancing для меня, я полностью беру этот сложный и нетривиальный вопрос на себя". Имхо, это ещё более не похоже на решение для "общего случая".


Давай-ка для начала определимся: либо у нас сложности с тем, как бы половчее раскидать загрузку по процессорам, либо конкуренция за разделяемые данные представляется нам критичным для быстродействия моментом. Если ты можешь привести пример ситуации, в которой эти два утверждения сосуществуют и не противоречат друг другу — будет интересно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[12]: GetCurrentProcessorNumber() под WinXP
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.01.08 14:18
Оценка:
Здравствуйте, remark, Вы писали:

R>Вот набросок алгоритма масштабируемого rw-mutex'а.


А из каких соображений следует делать такой вот универсальный и бесконечно масштабируемый мьютекс, одинаково эффективный для любого, заранее неизвестного алгоритма обработки данных? Мне только одно в голову приходит — для того, чтобы им пользовался какой-нибудь тупой программер Или есть более достойное применение?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[13]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 14:20
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


R>>Заметь, что делая жёсткую привязку потоков к процессорам ты фактически говоришь ОС "Пожалуйста, не делай load-balancing для меня, я полностью беру этот сложный и нетривиальный вопрос на себя". Имхо, это ещё более не похоже на решение для "общего случая".


ЕМ>Давай-ка для начала определимся: либо у нас сложности с тем, как бы половчее раскидать загрузку по процессорам, либо конкуренция за разделяемые данные представляется нам критичным для быстродействия моментом. Если ты можешь привести пример ситуации, в которой эти два утверждения сосуществуют и не противоречат друг другу — будет интересно.



Библиотека общего назначения. Надо сделать мьютекс.
В общем случае вполне естественно полагаем, что привязки потоков к процессорам нет, и конкуренция за разделяемые данные — критичный для быстродействия момент.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[13]: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 29.01.08 17:20
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


R>>Вот набросок алгоритма масштабируемого rw-mutex'а.


ЕМ>А из каких соображений следует делать такой вот универсальный и бесконечно масштабируемый мьютекс, одинаково эффективный для любого, заранее неизвестного алгоритма обработки данных? Мне только одно в голову приходит — для того, чтобы им пользовался какой-нибудь тупой программер Или есть более достойное применение?



Ну, не знаю. Для меня это очевидно. API всех ОС, и все серьёзные библиотеки это предоставляют. Почему универсальный? Мне кажется скорее корректнее ставить вопрос, почему *не* универсальный, если это не компромиссное решение. Бесконечно масштабируемый? Ну не бесконечно масштабируемый, а просто не деградирующий.




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: GetCurrentProcessorNumber() под WinXP
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 31.01.08 07:30
Оценка:
Здравствуйте, remark, Вы писали:

R>Заметь, что делая жёсткую привязку потоков к процессорам ты фактически говоришь ОС "Пожалуйста, не делай load-balancing для меня, я полностью беру этот сложный и нетривиальный вопрос на себя". Имхо, это ещё более не похоже на решение для "общего случая". Совсем не похоже.

R>Если ты не решишь хорошо вопрос load-balancing'а, то этот "банальный" вариант даст тебе не выигрыш в 2 раза, а проигрыш в N раз.

Кстати, заменяя SetThreadAffinityMask на SetThreadIdealProcessor, получаем шесть тактов на проход вместо пяти. Это в предельном случае, когда каждый поток полностью загружает процессор и работает только со своими данными — понятно, что здесь предпочтительна именно жесткая привязка. А если не загружает, то будет тебе и автоматический load balancing, и предпочтение в выборе процессора.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: GetCurrentProcessorNumber() под WinXP
От: remark Россия http://www.1024cores.net/
Дата: 31.01.08 16:49
Оценка:
Здравствуйте, remark, Вы писали:

R>Как получить функциональность GetCurrentProcessorNumber()/NtGetCurrentProcessorNumber() под WinXP/2k?



На AMD64 есть инструкция RDTSCP (Read Time-Stamp Counter and Processor ID), которая, помимо TS счётчика, возвращает так же идентификатор процессора.
Ложку дёгтя добавляет факт, что RDTSCP, в отличие от оригинальной RDTSC, сериализует выполнение конвейера, т.е. ждёт retirement'а всех предыдущих инструкций. Смысл в общем-то понятен — сделать более удобным и быстрым замер времени выполнения участков кода. Но блин, сделали бы возможность отдельно получать только Processor ID, и без сериализации, тогда бы и северный мост не нагружался.
А так вообще latecy: 41 core clocks + 16 Northbridge clocks.


R>


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