Предоставляет ли Intel MKL или подобная библиотека векторизованный способ подсчета количества элементов в массиве, удовлетворяющих некоторому условию в C? - PullRequest
0 голосов
/ 11 июля 2020

Проблема

Я работаю над реализацией и улучшением алгоритма оптимизации с некоторыми довольно большими массивами (от десятков миллионов чисел с плавающей запятой и выше) и использую в основном Intel MKL в C (не C ++, по крайней мере, не так далеко), чтобы выжать все возможное из производительности. Теперь я столкнулся с глупой проблемой - у меня есть параметр, который устанавливает максимумы и минимумы для подмножеств набора (десятков миллионов) коэффициентов. На самом деле применить эти максимумы и минимумы с помощью функций MKL легко - я могу создавать векторы одинакового размера с ограничениями для каждого элемента и использовать V? Fmax и V? Fmin для их применения. Но мне также необходимо учесть это отсечение в моей метрике ошибок c, которая требует от меня подсчета количества элементов, выходящих за рамки этих ограничений.

Однако я не могу найти функцию MKL, которая позволяет мне нужно делать такие вещи, как подсчет количества элементов, удовлетворяющих определенному условию, так же, как вы можете создавать и суммировать логические массивы, например, NumPy в Python или в MATLAB. Раздражает то, что когда я пытаюсь погуглить этот вопрос, я получаю ответы, относящиеся только к Python и R.

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

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

Обратите внимание, что мне необходимо уметь это в C, что для меня нецелесообразно переносить эту задачу на мой Python интерфейс, и что мне действительно необходимо сначала закодировать эту конкретную подпрограмму в C.

Спасибо!

Ответы [ 2 ]

1 голос
/ 18 июля 2020

MKL не предоставляет таких функций, но вы можете попробовать проверить другую библиотеку производительности - IPP, которая содержит набор пороговых функций, которые могут быть полезны в вашем случае. Пожалуйста, обратитесь к Справочнику разработчиков IPP, чтобы узнать больше - https://software.intel.com/content/www/us/en/develop/documentation/ipp-dev-reference/top/volume-1-signal-and-data-processing/essential-functions/conversion-functions/threshold.html

1 голос
/ 11 июля 2020

Если вы использовали c ++, count_if из библиотеки алгоритмов с политикой выполнения par_unseq может распараллелить и векторизовать счетчик. По крайней мере, на Linux обычно для этого используется Intel TBB.

В c это вряд ли будет так просто. Поскольку c не имеет таких понятий, как шаблоны, вызываемые объекты или лямбда-выражения, единственный способ специализации обобщенной c (предоставленной библиотекой) count() -функции - это передать указатель функции в качестве обратного вызова (например, qsort() делает). Если компилятору не удастся девиртуализировать и встроить обратный вызов, вы вообще не сможете векторизовать, оставив вам (возможно, распараллеленный потоком) скалярный код. OTOH, если вы используете, например, g cc vector intrinsics (мой любимый!), Вы получите векторизацию, но не распараллеливание. Вы можете попытаться комбинировать подходы, но я бы сказал, что переборщите себя и используйте c ++.

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

Для пример . g cc векторизует код на x86, если доступны хотя бы инструкции sse4 (-msse4). С AVX [2/512] (-mavx / -mavx2 / -mavx512f) вы можете получить более широкие векторы для одновременного выполнения большего количества элементов. В общем, если вы компилируете на том же оборудовании, на котором будете запускать программу, я бы рекомендовал позволить g cc автоматически определять оптимальные расширения набора команд (-march=native).

Обратите внимание, что в предоставленного кода, условия должны не использовать короткое замыкание или (||), потому что тогда чтение из max -вектора семантически запрещено, если сравнение с min -вектором было уже верно для текущего элемента, серьезно затрудняя векторизацию (хотя avx512 может потенциально векторизовать это с некоторой катастрофой c замедлением).

Я почти уверен, что g cc не совсем оптимально в коде, который он генерирует для avx512, так как он может делать k-reg (регистр маски) or в регистрах маски с kor[b/w/d/q], но, возможно, кто-то с большим опытом работы с avx512 (* cougth * Питер Кордес * кашляет *) мог бы на это повлиять.

...