Вопрос

Я читал в документации Visual C ++, что нескольким потокам безопасно считывать данные из одного и того же объекта.

Мой вопрос заключается в следующем:как процессор X86-64 с несколькими ядрами справляется с этим?

Допустим, у вас есть блок памяти объемом 1 МБ.Способны ли разные потоки буквально считывать одни и те же данные одновременно или ядра считывают по одному слову за раз, при этом только одному ядру разрешено считывать определенное слово за раз?

Это было полезно?

Решение

Разным ядрам разрешено не только считывать данные из одного и того же блока памяти, но и записывать их одновременно."Безопасно" это или нет, это совершенно другая история.Вам нужно внедрить в свой код какую-то защиту (обычно выполняемую с помощью семафоров или их производных) для защиты от того, чтобы несколько ядер сражались за один и тот же блок памяти способом, который вы специально не разрешаете.

Что касается размера памяти, которую ядро считывает за раз, то обычно это значение регистра, 32 бита для 32-битного процессора, 64 бита для 64-битного процессора и так далее.Даже потоковая передача выполняется dword за dword (посмотрите, например, на memcpy).

О том, как на самом деле работают несколько параллельных ядер, каждое ядро использует единую шину для чтения и записи в память, поэтому доступ к любым ресурсам (ОЗУ, внешним устройствам, процессору с плавающей запятой) осуществляется по одному запросу за раз, по одному ядру за раз.Однако фактическая обработка внутри ядра полностью параллельна.Переводы DMA также не блокируют шину, параллельные переводы помещаются в очередь и обрабатываются по одному за раз (я полагаю, не уверен в этом на 100%).

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

Другие советы

Если в вашем блоке размером 1 МБ действительно нет записей, то да, каждое ядро может читать из своей собственной строки кэша без каких-либо проблем, поскольку записи не фиксируются и, следовательно, проблем с когерентностью кэша не возникает.

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

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

Просто чтобы уточнить, как сказано в комментарии, доступ к оперативной памяти невозможен одновременно, поскольку архитектуры x86 и x64 реализуют единую шину, которая совместно используется между ядрами с SMP гарантирующий честный доступ к основной памяти.Тем не менее, эта ситуация скрыта кэшем каждого ядра, который позволяет каждому ядру иметь свою собственную копию данных.Для 1 МБ данных можно было бы столкнуться с некоторыми конфликтами, пока ядро обновляет свой кэш, но это было бы незначительно.

Несколько полезных ссылок:

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top