Одновременный доступ для чтения в массиве int []: это безопасно? Это быстро? - PullRequest
8 голосов
/ 17 февраля 2009

На четырехъядерном компьютере я рассматриваю распараллеливание алгоритма C # / .NET, который предполагает одновременное чтение несколькими потоками небольшого массива int []. Пока что, похоже, он работает довольно хорошо, но я не уверен, где указано, что параллельное чтение массива поточно-ориентировано в .NET. Есть указатели?

Тогда мне также интересно, действительно ли этот подход эффективен? Существуют ли ситуации, когда вам лучше на самом деле дублировать входные данные для каждого потока, чтобы не было одновременного чтения, и каждый массив (может быть?) Получает возможность кэшироваться вблизи аффинного процессора?

Есть какие-нибудь мысли о лучших практиках в отношении многоядерных процессоров?

Ответы [ 7 ]

18 голосов
/ 17 февраля 2009

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

Неизменяемые данные по своей природе являются поточно-ориентированными.

11 голосов
/ 17 февраля 2009

В вашем случае параллельное чтение вашего массива будет поточно-ориентированным.

Что касается эффективности ваших алгоритмов, то в зависимости от размера вашего массива, если он будет помещаться в кэш-памяти, вы можете увидеть превосходный прирост производительности, так как многоядерные процессоры эффективно «сражаются» за кэш в ЦП. Если они пытаются заполнить кэш той же информацией, они будут делиться, что означает увеличение количества обращений к кэшу и повышение производительности.

Предполагая, что ваш массив помещается в кеш ...

4 голосов
/ 17 февраля 2009

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

Я сомневаюсь, что вы тоже можете сделать что-то более быстрое.

3 голосов
/ 17 февраля 2009

Если на карту поставлены производительность и параллелизм .NET, я бы порекомендовал попробовать написать этот конкретный алгоритм на F #. Компилятор F # сгенерирует .NET-код, который имеет в 2-6 раз лучшую производительность .

3 голосов
/ 17 февраля 2009

Вас это не должно беспокоить. Одновременное чтение не является проблемой. Любое количество потоков может читать одну и ту же память одновременно.

2 голосов
/ 17 февраля 2009

Потоковая безопасность является проблемой только при обновлении данных. Если у вас есть несколько одновременных потоков обновление массива, вам нужно будет обернуть обновления (и читает, если обновления не атомарные) в механизме синхронизации. Для структуры данных только для чтения параллелизм не является проблемой.

1 голос
/ 28 марта 2009

Оператор присваивания не является потокобезопасным.

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

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

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

Это означает, что такие вещи, как if(), не работают надежно. Например,

if( int_array[5] == 10 )
{
}

Может сработать, когда значение в памяти int_array[5] больше не равно 10.

Я верю в C #, у вас должен быть доступ к вызовам функций Interlocked*(), таким как InterlockedCompareAndSwap(). Это позволит вам легко достичь безопасности потока в этом случае.

...