Как эффективно получить доступ к нескольким элементам массива в С++?

Это мой первый пост, надеюсь, я буду соответствовать стандартам...

Я перевожу на c++ (в котором я совсем новичок) программу, изначально написанную на MATLAB из соображений эффективности. Фрагмент кода, над которым я сейчас работаю, возобновляет доступ к различным индексам вектора (матрицы) за один шаг. Например, если M1 — это матрица размера, скажем, 10x15, программа определит новую матрицу следующим образом:

idxs1 = [1 2 3];
idxs2 = [1 2 3 4 5];
M2 = M1 (idxs1 , idxs2);

результирующий M2 в виде матрицы размера 3x5. Теперь я предполагаю, что MATLAB на самом деле делает доступ один за другим к различным местам M1, заданным индексами, а затем создает M2, переупорядочивая множество полученного содержимого, и все это очень эффективно.

Мой вопрос: как я могу воспроизвести такой механизм в c++? Насколько я знаю, нет прямого доступа к различным индексам массива подряд, а используемый мной цикл for кажется довольно громоздким. Может быть, есть какой-то разумный способ сделать это, не требуя «слишком много» процессорного времени? Кроме того, в образовательных целях я был бы признателен, если бы кто-нибудь объяснил, что на самом деле делает MATLAB при выполнении такой операции.

Заранее благодарим и приносим извинения за возможные неудобства!

P.S. На всякий случай, если это что-то добавит к вопросу, я работаю с файлами MEX, чтобы связать оба языка. P.S2: Кстати, я нашел несколько связанных вопросов, но относительно других языков:


person Alejo Alberti    schedule 04.01.2016    source источник
comment
Вам будет очень трудно повысить эффективность Matlab.   -  person 1201ProgramAlarm    schedule 04.01.2016
comment
Почему вы думаете, что будет легко превзойти Matlab с точки зрения эффективности? Matlab в основном использует BLAS и LAPACK для матричных операций. Эти библиотеки изначально были написаны на фортране. Вы можете использовать эти функции, используя некоторые c обертки. Matlab также использует тип матрицы, называемый mxArray. Я полагаю, что можно использовать и другие матричные библиотеки, но вам следует избегать написания всего самостоятельно, если вы не скучающий математический гений.   -  person patrik    schedule 04.01.2016
comment
Библиотека матриц C++ с несмежными представлениями подматриц. также имеет интерфейс MEX   -  person hbrerkere    schedule 04.01.2016
comment
Большое спасибо за полезные ответы. Я неправильно выразился, предполагая, что пытался победить MATLAB =) Что я на самом деле делаю, так это перевожу на C++, чтобы потом перейти на CUDA. При этом получается, что моя программа на самом деле работает быстрее, чем MATLAB, но только если размер системы достаточно мал, MATLAB превосходит мою реализацию для больших систем (т.е. матриц) и, кроме того, занимает примерно такое же количество времени. независимо от размера. Это достижение благодаря умному кодированию (не мной), которое я надеюсь воспроизвести через Armadillo. Спасибо за ответы! знак равно   -  person Alejo Alberti    schedule 07.01.2016


Ответы (3)


«Armadillo — это высококачественная библиотека линейной алгебры C++, целью которой является хороший баланс между скоростью и простотой использования.

Полезно для разработки алгоритмов непосредственно на C++ или быстрого преобразования исследовательского кода в производственные среды; синтаксис (API) намеренно похож на Matlab"

Ссылка: http://arma.sourceforge.net/

person Severin Pappadeux    schedule 04.01.2016
comment
Именно то, что я искал. Теперь заставить его работать с файлами MEX было не просто... Большое спасибо! - person Alejo Alberti; 07.01.2016
comment
@AlejoAlberti рад слышать! Если вы удовлетворены ответом, примите его и давайте двигаться дальше - person Severin Pappadeux; 07.01.2016

Структуры данных математических программ могут быть одними из самых сложных. Я даже не могу понять, что на самом деле делает 3-я строка вашего примера, поэтому я даже не могу догадаться, как MATLAB что-либо реализует.

Что я могу вам сказать, так это то, что одна строка MATLAB почти наверняка скрывает массу операций. Если вы хотите воссоздать его, вам просто нужно создать служебную функцию с парой циклов for, которые копируют все правильные индексы один за другим. В конечном счете, это не может сильно отличаться от того, что делает один MATLAB.

Если у вас есть масса матричных операций, которые вам нужно поддерживать, и вы работаете над большим проектом, вы можете захотеть найти библиотеку матриц C++. Мне нечего порекомендовать, но Boost — популярная библиотека C++ для многих целей, включая матрицы. (Вы также можете создать свою собственную структуру данных, но не рекомендуется для новичков.)

person Paul K    schedule 04.01.2016
comment
Отличный совет, и определенно написание структуры данных пока не входит в мою лигу. На самом деле, эта библиотека матриц C++ - это предложение @Severin, patrik и hbrerkere, поэтому я думаю, что вы все стремитесь к одному и тому же. Несмотря на то, что я не попал в документацию Boost, я думаю, что выберу Armadillo из-за сходства синтаксиса с MATLAB (а также из-за проблем со скоростью - stackoverflow.com/questions/14414906/, хотя сравнения выполняются не очень тщательно). Спасибо за ответ! - person Alejo Alberti; 07.01.2016

Что именно делает MATLAB точно, не уточняется, и вполне может отличаться от случая к случаю в зависимости от индексов, и даже для заданного набора индексов это может отличаться от машины к машине. Так что не будем спекулировать.

В частности, не указано, копирует ли MATLAB M1 физически. Такую копию можно подделать, что экономит время. Этот метод известен как «копирование при записи».

В C++ это тоже возможно, но сложнее. Кроме того, ни один из существующих классов контейнеров не поддерживает его.

Если вы собираетесь копировать элементы, CPU не будет узким местом. Вместо этого вас будет ограничивать шина памяти. Это особенно верно, когда индексы не являются смежными. Для матрицы 3x5 во времени будут преобладать накладные расходы — смежность пока не имеет значения.

person MSalters    schedule 04.01.2016
comment
Спасибо за ваш ответ и полностью согласен с предпосылкой отсутствия спекуляций. Просто подумал, что может быть какая-то стандартная настройка, которую я проигнорировал. Что нужно моей программе, так это взять за один шаг (избегая явного for) часть матрицы, не обязательно копируя ее (что-то вроде указателя на множество областей памяти, которые, очевидно, не существуют как таковые). Отличное предложение по поводу автобуса! Хорошо, что индексы смежные. А матрицы размером ~150000 x 100, так что лучше не копировать, да? знак равно - person Alejo Alberti; 07.01.2016