WedX - журнал о программировании и компьютерных науках

Как эффективно выполнять рассеянное суммирование с помощью SSE/x86

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

[198, {0.4,0,1}],  [775, {0.25,0.8,0}],  [12, {0.5,0.5,0.02}]

и мне нужно суммировать их в память так:

memory[198] += {0.4,0,1}
memory[775] += {0.25,0.8,0}
memory[12]  += {0.5,0.5,0.02}

Чтобы усложнить ситуацию, несколько потоков будут делать это одновременно, читая из разных входных потоков, но суммируя в одну и ту же память. Я не ожидаю, что будет много споров за одни и те же места памяти, но они будут. Наборы данных будут довольно большими — несколько потоков по 10+ ГБ каждый, которые мы будем транслировать одновременно с нескольких твердотельных накопителей, чтобы получить максимально возможную пропускную способность чтения. Я предполагаю SSE для математики, хотя это, конечно, не должно быть так.

Результаты какое-то время не будут использоваться, поэтому мне не нужно засорять кеш... но я суммирую в память, а не просто записываю, так что я не могу использовать что-то вроде MOVNTPS, верно? Но поскольку потоки не будут сильно наступать друг на друга, как я могу сделать это без больших затрат на блокировку? Вы бы сделали это с ограждением памяти?

Спасибо за любую помощь. Я могу предположить Nehalem и выше, если это имеет значение.

28.01.2012

  • Я предполагаю, что вы получаете доступ к плотно упакованному массиву в памяти. Поскольку ширина каждого элемента составляет 3 числа с плавающей запятой, большинство элементов не будут выровнены по 16-байтовым границам, что делает работу SSE чрезвычайно медленной. Кроме того, как показывает ваш пример, для доступа к данным нет простого шаблона, что затрудняет предварительную выборку. В целом это затруднит использование потенциала SSE. Вероятно, лучше всего будет просто сделать это на C/++ и позволить компилятору делать магию, я сомневаюсь, что есть много возможностей улучшить это с помощью SIMD. 29.01.2012
  • Я могу использовать 4-векторы с плавающей запятой в памяти, чтобы без проблем получить 16-битное выравнивание. Чем здесь может помочь предварительная выборка? Это наверняка облегчило бы суммирование, но предварительная выборка+сумма+запись открывает мне все виды условий гонки с другими потоками, делающими то же самое. 29.01.2012
  • Выравнивание не имеет значения, когда память была предварительно выбрана, но когда нет, вам придется либо использовать невыровненное перемещение, либо обеспечить выравнивание данных, чего вы не можете сделать, когда вы обращаетесь к плотно упакованному массиву, где элементы имеют ширину 3 поплавка. 29.01.2012

Ответы:


1

Вы можете использовать спин-блокировки для синхронизированного доступа к элементам массива (по одному на идентификатор) и SSE для суммирования. В C++, в зависимости от компилятора, могут быть доступны встроенные функции, например. потоковые расширения SIMD и InterlockExchange в Visual C++.

29.01.2012

2

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

Запустите один поток на процессор. Статически распределить данные назначения между этими потоками. И предоставьте каждому потоку одни и те же входные данные. Это позволяет лучше использовать архитектуру NUMA. И позволяет избежать дополнительного трафика памяти для синхронизации потоков.

В случае однопроцессорной системы используйте только один поток для доступа к данным назначения.

Вероятно, единственное практическое применение большего количества ядер в ЦП — это загрузка входных данных дополнительными потоками.

Одной из очевидных оптимизаций является выравнивание данных назначения по 16 байтам (чтобы избежать касания двух строк кэша при доступе к одному элементу данных).

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

Что касается загрязнения кеша выходными данными, MOVNTPS здесь не поможет, но вы можете использовать PREFETCHNTA для предварительной выборки элементов выходных данных на несколько шагов вперед, сводя к минимуму загрязнение кеша. Улучшит ли это производительность или ухудшит ее, я не знаю. Это позволяет избежать очистки кеша, но оставляет большую часть кеша неиспользованной.

29.01.2012
Новые материалы

Как проанализировать работу вашего классификатора?
Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

Учебные заметки: создание моего первого пакета Node.js
Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

ИИ в аэрокосмической отрасли
Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


Для любых предложений по сайту: [email protected]