Должны ли потоки действовать на отдельную память? - PullRequest
0 голосов
/ 06 июля 2018

У меня есть программа на C ++, задачей которой является анализ потока двоичных данных (обычно это файл на диске) и извлечение некоторой информации. Эта задача «без памяти», что означает, что результат каждого шага не зависит от предыдущего. Из-за этого я подумал ускорить его, передав данные отдельным потокам для повышения производительности.

Пока что данные читаются в блоках по 1 ГБ за раз и сохраняются в массиве, чтобы избежать узких мест ввода / вывода. Стоит ли разделять данные в n чанках / массивах (где n - количество потоков) или единый массив, к которому обращаются несколько потоков, не является проблемой?

У меня есть программа на C ++, задачей которой является анализ потока двоичных данных (обычно это файл на диске) и извлечение некоторой информации. Эта задача «без памяти», что означает, что результат каждого шага не зависит от предыдущего. Из-за этого я решил ускорить его, передав данные отдельным потокам для повышения производительности.

Пока что данные читаются в блоках по 1 ГБ за раз и сохраняются в массиве, чтобы избежать узких мест ввода / вывода. Стоит ли разделять данные в n чанках / массивах (где n - количество потоков) или единый массив, к которому обращаются несколько потоков, не является проблемой?

РЕДАКТИРОВАТЬ 1: данные и спецификации анализа Я понимаю, что формулировка проблемы может быть слишком широкой, как указано в одном из комментариев. Я попытаюсь углубиться в детали.

Анализируемые данные представляют собой серию 64-разрядных целых чисел без знака, сгенерированных так называемым «цифровым преобразователем времени» (TDC), в котором хранится информация о метке времени для некоторого события, которое они регистрируют. Мой TDC имеет несколько каналов, поэтому каждая временная метка содержит информацию о том, какой канал сработал (первые 3 бита), был ли это триггер с нарастающим или падающим фронтом (4-й бит), и фактическое время (в тактах с момента включения TDC, последнее 60 бит).

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

Эти файлы могут быть довольно большими (десятки ГБ), а количество временных меток может быть огромным (один такт - 80 пико секунд).

Пока я только один раз просматриваю весь файл, и идея состояла в том, чтобы «разрезать» его на более мелкие части, которые затем будут анализироваться различными потоками. Возможная потеря событий между разрезами является приемлемой для меня, так как, самое большее, будет 2 на сотни тысяч.

Конечно, они будут читать только данные из файла / памяти. Я могу записать счетчики совпадений в трех отдельных переменных, а затем суммировать их по окончании всех потоков, если это помогает избежать проблем с синхронизацией.

Надеюсь, теперь все стало яснее.

1 Ответ

0 голосов
/ 06 июля 2018

Да, один и тот же массив может быть доступен для нескольких потоков: если потоки только читают массив (что здесь имеет место), у вас не будет ложных эффектов совместного использования.

А чтобы оптимизировать использование кэша, вы могли бы заставить каждый поток читать последовательные элементы массива (т.е. не чтение с чередованием между потоками).

В качестве дополнительного примечания вы можете пересмотреть блок 1 ГБ: это много! Вы измерили, что это лучше, чем, скажем, 1 МБ или 10 КБ?

Вы также можете распараллелить «чтение файлов» (по одному небольшому куску за раз) и «обработку прочитанного контента» (используя много потоков, как вы), используя (как минимум) 2 массива (один обработано, другой получит следующее чтение)

...