Низкая производительность умножения матриц с использованием MTJ/Netlib (нативный)
Мне нужно умножить большие матрицы размером 5000x5000 до 20000x20000. У меня возникла проблема с поиском библиотеки, которая имеет разреженные матрицы и все же может выполнять быстрое умножение.
Прежде всего, я прочитал предыдущий вопрос о производительности библиотек матрицы Java ( Производительность математических библиотек Java?). Основываясь на верхнем ответе, я решил пойти с JBLAS, так как он был одним из самых быстрых. В моем случае для умножения матрицы 5000x5000 потребовалось примерно 50 с или около того, что намного медленнее, чем Matlab, но все же терпимо.
Проблема в том, что матрицы могут быть довольно большими (до 20К на 20К или более), но они, как правило, редки. Только 30% элементов в матрице не равны нулю. JBLAS не предоставляет какой-либо реализации разреженных матриц, поэтому объем памяти, необходимый для хранения большой плотной матрицы, может оказаться слишком большим. Я попытался переключиться на MTJ/Netlib, так как он должен быть одной из лучших библиотек в тесте с разреженной матрицей. В записке здесь ( https://github.com/fommil/netlib-java/) говорится, что для достижения наилучшей производительности я должен скомпилировать собственный BLAS на своей машине. Поэтому я скачал OpenBLAS, скомпилировал и установил его. Я также запускаю несколько команд для установки библиотеки OpenBLAS в Ubuntu 13.10:
$ cd ~/build/OpenBLAS
$ make
$ sudo make install PREFIX=/usr/local/openblas
$ sudo cat "/usr/local/openblas/lib" > /etc/ld.so.conf.d/openblas.conf
$ sudo ldconfig
$ sudo update-alternatives --install /usr/lib/libblas.so.3 libblas.so.3 /usr/local/openblas/lib/libopenblas.so 90
$ sudo update-alternatives --config libblas.so.3
Я выбрал свою скомпилированную библиотеку OpenBLAS на последнем этапе обновления альтернатив. Я предполагаю, что после этого Netlib забирает мою скомпилированную библиотеку OpenBLAS и использует ее. Я также запустил некоторые тесты с http://r.research.att.com/benchmarks/R-benchmark-25.R и наблюдал некоторое ускорение в до (используя blas по умолчанию из ubuntu) и после случая (используя мой скомпилирован OpenBLAS).
Однако производительность умножения матриц-матриц в MTJ все еще очень низкая. Например, у меня есть две матрицы A = 5824x5824, W = 5824x4782. Я умножаю их так на Java
Matrix AW = new FlexCompRowMatrix(A.numRows(), W.numColumns());
A.mult(W, AW);
Код работает уже более 45 минут, этого достаточно, чтобы напечатать весь этот пост, и он все еще не заканчивается. Используя JBLAS, такое же умножение матриц займет менее 1 минуты. Есть что-то, что я пропустил?
Спасибо!
2 ответа
JBLAS выполняет плотные матричные операции. MJT делает и плотным и разреженным. Использование "разреженных" матриц плотным способом идет медленно. FlexCompRowMatrix
создает разреженную матрицу.
То, что вы хотите сделать, чтобы сравнить непосредственно с JBLAS, это:
Matrix a = new DenseMatrix(5000,5000);
Matrix b = new DenseMatrix(5000,5000);
Matrix c = new DenseMatrix(5000,5000);
a.multAdd(b, c);
Производительность при использовании MJT+OpenBlas должна быть примерно такой же, как у MatLab.
См. http://jeshua.me/blog/NetlibJavaJNI и обратите внимание, что вам может потребоваться обновить собственные имена пакетов в тесте, чтобы продемонстрировать их использование.
например, может потребоваться изменить: Class javaBlasClass = Class.forName("org.netlib.blas.JBLAS"); to: Class javaBlasClass = com.github.fommil.netlib.BLAS.class;