#c #openmp #vectorization #eigen #eigen3
#c #openmp #векторизация #eigen #eigen3
Вопрос:
У меня есть Eigen::Matrix2Xf
строка, в которой позиции X и Y, а cols выступают в качестве индекса списка
Я хотел бы иметь сумму столбцов (по строкам), в которых выполняется какое-либо условие столбца, вот пример кода:
Eigen::Vector2f computeStuff(Eigen::Matrix2Xf amp; values, const float max_norm){ const auto mask = values.colwise().norm().array() lt; max_norm; return mask.select(values.colwise(), Eigen::Vector2f::Zero()).rowwise().sum(); }
Но этот код не компилируется, жалуясь на типы матриц if/else, каков правильный (и вычислительно более быстрый) способ сделать это?
Также я знаю, что есть аналогичный вопрос с ответом, но они создают новый Eigen::Matrix2Xf
с отфильтрованными значениями, заданными маской, этот код предназначен для запуска внутри #pragma omp parallel for
, поэтому основная идея состоит в том, чтобы не создавать новую матрицу для поддержания согласованности кэша
Спасибо
Комментарии:
1. Скажем
values
, 2х4 … это 2 строки и 4 столбца. Тогдаvalues.colwise().norm().array() lt; max_norm
будет 1х4, одна строка и четыре столбца. Затем вы говорите, что хотите суммировать строки вvalues
этомmask
списке …values
содержит только 2 строки иmask
четыре столбца. Вы имеете в виду, что хотите суммировать столбцы ,values
которые выбирает маска?2. @jwezorek да, именно это, извините, если я не был ясен, я задал вопрос
3. другое дело, как выход может быть a
vector2f
? Результатом, если я понимаю, что вы пытаетесь сделать, будет вектор строк с любым количеством столбцов на входе. Если вы хотите, чтобы в нем были только ненулевые столбцы, и знаете, что их будет только два или что-то еще, с чем вы не сможете этого сделать.select(...)
.4. результатом будет a
vector2f
, идея состоит в том, чтобы замаскировать некоторые столбцы значений матрицы, а затем выполнить операцию сокращения по строкам, я хочу, чтобы была только сумма по строкам замаскированных столбцов
Ответ №1:
Основная проблема с вашим кодом заключается в том, что .select( ... )
по крайней мере один из его аргументов должен иметь ту же форму, что и маска. Аргументами могут быть две матрицы или матрица и скаляр или наоборот, но во всех случаях матрицы должны иметь форму маски.
В вашем коде mask
есть вектор строк, но values
это матрица 2 на x. Один из способов справиться с этим-просто скопировать вектор строк в матрицу из двух строк:
#include lt;Eigen/Densegt; #include lt;iostreamgt; Eigen::Vector2f computeStuff(Eigen::Matrix2Xfamp; values, const float max_norm) { auto mask = (values.colwise().norm().array() lt; max_norm).replicate(2, 1); return mask.select(values, 0).rowwise().sum(); } int main() { Eigen::Matrix2Xf mat(2,4); mat lt;lt; 1, 4, 3, 2, 1, 2, 4, 3; auto val = computeStuff(mat, 5); std::cout lt;lt; val; return 0; }
В приведенном выше mask
будет:
1 1 0 1 1 1 0 1
т. е. строка 1 1 0 1
дублируется один раз. Затем mask.select(values, 0)
уступает
1 4 0 2 1 2 0 3
таким образом, результат будет
7 6
что, я думаю, именно то, чего вы хотите, если я правильно понимаю вопрос.