Библиотека линейной алгебры C ++ eigen3, странные результаты производительности - PullRequest
4 голосов
/ 26 марта 2012

Я уже некоторое время использую библиотеку линейной алгебры eigen3 в c ++, и я всегда пытался воспользоваться преимуществами производительности векторизации. Сегодня я решил проверить, насколько векторизация действительно ускоряет мои программы. Итак, я написал следующую тестовую программу:

--- eigentest.cpp ---

#include <eigen3/Eigen/Dense>
using namespace Eigen;

#include <iostream>

int main() {
        Matrix4d accumulator=Matrix4d::Zero();
        Matrix4d randMat = Matrix4d::Random();
        Matrix4d constMat = Matrix4d::Constant(2);
        for(int i=0; i<1000000; i++) {
                randMat+=constMat;
                accumulator+=randMat*randMat;
        }
        std::cout<<accumulator(0,0)<<"\n"; // To avoid optimizing everything away
        return 0;
}

Затем я запустил эту программу после компиляции с различными параметрами компилятора: (Результаты не единичны, многие прогоны дают схожие результаты)

$ g++ eigentest.cpp  -o eigentest -DNDEBUG -std=c++0x -march=native
$ time ./eigentest
5.33334e+18

real    0m4.409s
user    0m4.404s
sys 0m0.000s
$ g++ eigentest.cpp  -o eigentest -DNDEBUG -std=c++0x
$ time ./eigentest 
5.33334e+18

real    0m4.085s
user    0m4.040s
sys 0m0.000s
$ g++ eigentest.cpp  -o eigentest -DNDEBUG -std=c++0x -march=native -O3
$ time ./eigentest 
5.33334e+18

real    0m0.147s
user    0m0.136s
sys 0m0.000s
$ g++ eigentest.cpp  -o eigentest -DNDEBUG -std=c++0x -O3
$time ./eigentest
5.33334e+18

real    0m0.025s
user    0m0.024s
sys 0m0.000s

А вот моя соответствующая информация о процессоре:

model name  : AMD Athlon(tm) 64 X2 Dual Core Processor 5600+
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow extd_apicid pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy 3dn

Я знаю, что векторизация не происходит, когда я не использую опцию компилятора -march=native, потому что, когда я ее не использую, я никогда не получаю ошибку сегментации или неверный результат из-за векторизации, в отличие от в случае, если я использую его (с -NDEBUG).

Эти результаты приводят меня к мысли, что, по крайней мере, моя векторизация процессора с помощью eigen3 приводит к более медленному выполнению. Кого я должен винить? Мой процессор, eigen3 или gcc?

Редактировать: чтобы устранить любые сомнения, я сейчас попытался добавить опцию компилятора -DEIGEN_DONT_ALIGN в тех случаях, когда я пытаюсь измерить производительность случая отсутствия векторизации, и результаты совпадают. Кроме того, когда я добавляю -DEIGEN_DONT_ALIGN вместе с -march=native, результаты становятся очень близки к случаю без -march=native.

1 Ответ

9 голосов
/ 26 марта 2012

Кажется, что компилятор умнее, чем вы думаете, и все же оптимизирует многие вещи.

На моей платформе я получаю около 9 мс без -march=native и около 39 мс с -march=native.Однако, если я заменю строку над возвратом на

std::cout<<accumulator<<"\n";

, то время изменится на 78 мс без -march=native и около 39 мс с -march=native.

Таким образом, кажется, что безВекторизация, компилятор понимает, что вы используете только (0,0) элемент матрицы, и поэтому он только вычисляет этот элемент.Однако эта оптимизация не может быть выполнена, если векторизация включена.

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

...