자바 매트릭스 수학 라이브러리의 성능은? [닫은]


151

우리는 런타임이 행렬 연산에 의해 구속되는 것을 계산하고 있습니다. (관심이 있다면 아래에 몇 가지 세부 사항이 있습니다.)

사람들은 행렬 수학 (예 : 곱하기, 역함수)을위한 Java 라이브러리의 성능에 경험이 있습니까? 예를 들면 다음과 같습니다.

나는 아무것도 찾지 못했다.


속도 비교 세부 사항 :

인텔 FORTRAN (ifort (IFORT) 10.1 20070913)을 사용하고 있습니다. Apache commons math 1.2 매트릭스 ops를 사용하여 Java (1.6)로 다시 구현했으며 모든 정확도에 동의합니다. (Java로 원하는 이유가 있습니다.) (Java는 두 배, Fortran real * 8). 포트란 : 6 ​​분, Java 33 분, 동일한 머신. jvisualm 프로파일 링은 RealMatrixImpl에서 많은 시간을 보냈습니다. Fortran은 Atlas BLAS 루틴 (dpotrf 등)을 사용하고 있습니다.

분명히 이것은 각 언어의 코드에 따라 달라질 수 있지만 대부분의 경우 동등한 행렬 연산에 있다고 생각합니다.

라이브러리를 포함하지 않는 여러 다른 계산에서 Java는 훨씬 느리지 않고 때로는 훨씬 빠릅니다.


까다로운 행렬 수학 연산은 최소한 O (n ^ 3)입니다 ... 더 나빠질
수록

2
왜 역수가 필요합니까? 거의 모든 응용 프로그램의 경우 실제 역수가 필요하지 않습니다. 역산을 계산하는 것은 안정성 문제 때문에 나쁜 생각입니다.
잉 샤오

1
@Calyth : 그렇습니다, 우리는 시간을 할 수있었습니다. 다른 사람들이 이미 가지고 있는지 궁금했습니다. @Ying Xiao : 그렇습니다. 그 반대는 피해야합니다. 그러나이 계산은 가장 간단하게 사용됩니다. en.wikipedia.org/wiki/…를 참조하십시오 .
dfrankow

2
@Calyth 잘못 되었으니, 나누기 및 정복 방법을 사용하는 O (n ^ 3)보다 더 효율적인 방법이 있습니다.
starblue

1
가장 빠른 기본 성능은 JCublas입니다. 빠른 선형 대수가 필요한 경우 GPU가 필요합니다. clMath가있는 JOCL도 작동하고 CPU에 이식 가능하며 (다시 컴파일하지 않은 다중 플랫폼) 테스트하지 않았습니다.
Aleksandr Dubinsky

답변:


98

내 2 센트 만 추가하면됩니다. 이 라이브러리 중 일부를 비교했습니다. 나는 자신과 함께 3000 곱하기 3000의 곱셈 행렬을 곱하려고 시도했다. 결과는 다음과 같습니다.

C / C ++, Octave, Python 및 R과 함께 멀티 스레드 ATLAS를 사용하는 데 걸리는 시간은 약 4 초였습니다.

Java와 함께 Jama를 사용하는 데 걸리는 시간은 50 초입니다.

Java와 함께 Colt 및 Parallel Colt를 사용하면 소요 시간이 150 초였습니다!

JBLAS를 Java와 함께 사용하면 JBLAS가 멀티 스레드 ATLAS를 사용하므로 약 4 초가 걸렸습니다.

그래서 Java 라이브러리가 너무 잘 수행되지 않았다는 것이 분명했습니다. 그러나 누군가 Java로 코딩해야하는 경우 가장 좋은 방법은 JBLAS입니다. Jama, Colt 및 Parallel Colt는 빠르지 않습니다.


3
멀티 코어 머신을 사용하고 있다고 생각하므로 라이브러리가 멀티 코어를 사용하는지 여부에 따라 이러한 결과가 크게 영향을 받습니까? 예를 들어 mpi 또는 hadoop 등을 사용하여 병렬화하는 경우 mpi / hadoop 구현이 병렬화를 처리 하므로 중요한 시간은 실제로 단일 코어 시간입니다. (적어도, jblas는 jama보다 2.5 배 빠르며, jama보다 10 배 빠르지 않았습니다.)
Hugh Perkins

17
방금 netlib-java v1.0을 공개했습니다 ... 성능이 Fortran 코드와 동일합니다 (때로는 능가). 사용자 코드를 변경하지 않고도 머신 최적화 네이티브를 사용할 수 있습니다. 저수준 선형 대수 라이브러리를 찾을 때 이것을 고려하십시오. 또한 netlib-java를 사용하는 MTJ 를 유지 합니다. 스칼라에서는 Breeze (또한 제공 netlib-java)
fommil을 사용하십시오.

4
ND4j와 java를 사용하면 비교적 오래된 랩탑이 219 밀리 초 안에 제안 된 곱셈을 완료합니다. python + numpy가 349 millis
bennyl

2
그리고 nd4j 사용에 대한 마지막 의견을 추가하기 위해 네이티브 플랫폼을 백엔드로 사용했습니다. cuda- 플랫폼을 사용하는 경우 약 1 밀리 초가 소요됩니다
bennyl

벤치 마크 용 코드를 어딘가에 게시 했습니까?
bruziuz

108

저는 JMatBench (Java Matrix Benchmark)의 저자 이며이 토론에 대해 생각하겠습니다.

Java 라이브러리 간에는 상당한 차이가 있으며 전체 작업 범위에서 확실한 승자는 없지만 최신 성능 결과 에서 볼 수있는 명확한 리더는 거의 없습니다 (2013 년 10 월).

"큰"행렬로 작업하고 기본 라이브러리를 사용할 수있는 경우 시스템 최적화 netlib을 갖춘 MTJ 는 확실한 승자입니다 (약 3.5 배 더 빠름) . 순수한 Java 솔루션이 필요한 경우 MTJ , OjAlgo , EJMLParallel Colt 가 적합합니다. 작은 행렬의 경우 EJML이 확실한 승자입니다.

언급하지 않은 라이브러리는 중요한 성능 문제를 나타내거나 주요 기능이 누락되었습니다.


6
벤치 마크가 정말 편리하다고 언급했습니다! 시간을 내 주셔서 감사합니다.
hohonuuli

1
JBLAS는 9 월 13 일 현재 SVD를 지원하는 것으로 보입니다 : mikiobraun.github.io/jblas/javadoc/org/jblas/…
Leopd

훌륭한 작품입니다.
webpat

평가했지만 라이브러리에 결과를 게시하지 않은 라이브러리 및 그 이유가있는 목록이 있습니까?
Kevin Krumwiede 님이

1
MTJ는 포기 보인다 : 저장소가 보관하고 마지막은 2016 년에 있었다 커밋
다닐라 Piatov을

51

저는 jblas의 주요 저자이며 2009 년 12 월 말에 1.0 버전을 출시했다고 지적하고 싶었습니다. 포장에 많은 노력을 기울였습니다. 이제 ATLAS 및 JNI 라이브러리로 "뚱뚱한 병"을 다운로드 할 수 있습니다. Windows, Linux, Mac OS X, 32 및 64 비트 (Windows 제외). 이런 식으로 jar 파일을 클래스 경로에 추가하여 기본 성능을 얻을 수 있습니다. http://jblas.org 에서 확인하십시오 !


2
작업에서 영감을, 나는에서 비슷한 일했다 NETLIB - 자바를 ;-)
fommil

2
하하, 나도 jeigen :-)
휴 퍼킨스

JogAmp도 동일합니다 (jogamp-fat.jar 참조). 좋은 생각 :)
gouessej

8

실제로 특정 라이브러리에 대해서는 언급 할 수 없지만 원칙적으로 Java에서 이러한 작업이 느려질 이유는 거의 없습니다. 핫스팟은 일반적으로 컴파일러가 기대하는 종류의 작업을 수행합니다. Java 변수에 대한 기본 수학 연산을 해당 기계 명령어 (SSE 명령어를 사용하지만 연산 당 하나만 사용)로 컴파일합니다. 배열의 요소에 대한 액세스는 "원시"MOV 명령어를 사용하도록 컴파일됩니다. 가능할 때 레지스터에 변수를 할당하는 방법을 결정합니다. 프로세서 아키텍처를 활용하기 위해 명령어의 순서를 바꿉니다. 언급 한 바와 같이 Hotspot은 SSE 명령어 당 하나의 작업 만 수행한다는 점이 예외입니다. 원칙적으로 명령 당 여러 작업을 수행하는 환상적인 최적화 된 매트릭스 라이브러리를 가질 수 있습니다. 예를 들어, 특정 FORTRAN 라이브러리가 그러한 라이브러리를 가지고 있는지 또는 그러한 라이브러리가 존재하는지 여부는 알 수 없습니다. 그렇다면 Java (또는 적어도 Hotspot)와 경쟁 할 수있는 방법이 없습니다 (물론 Java에서 호출하도록 최적화를 사용하여 고유 라이브러리를 작성할 수는 있습니다).

이 모든 것이 무엇을 의미합니까? 잘:

  • 원칙적으로, 더 나은 성능의 라이브러리를 찾는 것이 가치가 있지만 불행히도 나는 그것을 추천 할 수는 없습니다.
  • 성능이 정말 중요하다면, 자신의 매트릭스 연산을 코딩하는 것을 고려할 것입니다. 라이브러리가 일반적으로 할 수없는 특정 최적화 또는 사용하지 않는 특정 라이브러리를 수행 할 수 있기 때문입니다 ( 멀티 프로세서 머신, 라이브러리가 실제로 멀티 스레드인지 확인)

행렬 연산에 방해가되는 경우는 데이터를 서로 정렬하는 순서대로 데이터를 저장해야하기 때문에 행 단위 및 열 단위로 (예 : 행렬 곱셈)를 통과해야하는 경우 발생하는 데이터 지역성 문제입니다. 그러나 코드를 직접 작성하는 경우 연산을 결합하여 데이터 지역성을 최적화 할 수 있습니다 (예 : 변환에 행렬을 곱하는 경우 결합 대신 전용 함수를 작성하면 열 순회를 행 순회로 전환 할 수 있음) 두 개의 라이브러리 함수). 평소와 같이 라이브러리는 더 빠른 개발을 위해 최적의 성능을 제공합니다. 성능이 얼마나 중요한지 결정해야합니다.


8

방금 Apache Commons Math와 jlapack을 비교했습니다.

테스트 : 임의의 1024x1024 매트릭스의 특이 값 분해.

머신 : Intel (R) Core (TM) 2 Duo CPU E6750 @ 2.66GHz, Linux x64

옥타브 코드 : A = rand (1024); 틱; [U, S, V] = svd (A); toc

결과 실행 시간
-------------------------------------------------- -------
옥타브 36.34 초

JDK 1.7u2 64 비트
    jlapack dgesvd 37.78 초
    Apache Commons Math SVD 42.24 초


JDK 1.6u30 64 비트
    jlapack dgesvd 48.68 초
    Apache Commons Math SVD 50.59 초

기본 루틴
C에서 호출 된 Lapack * : 37.64 초
인텔 MKL 6.89 초 (!)

내 결론은 JDK 1.7에서 호출 된 jlapack이 lapack의 기본 이진 성능에 매우 가깝다는 것입니다. 리눅스 배포판과 함께 제공되는 lapack 바이너리 라이브러리를 사용하고 dgesvd 루틴을 호출하여 U, S 및 VT 행렬도 가져 왔습니다. 모든 테스트는 매번 정확히 동일한 매트릭스에서 배정 밀도를 사용하여 수행되었습니다 (옥타브 제외).

면책 조항-나는 선형 대수학의 전문가가 아니며 위의 라이브러리와 관련이 없으며 엄격한 벤치 마크가 아닙니다. JDK 1.7에서 1.6으로의 성능 향상뿐만 아니라 commons math SVD에서 jlapack으로의 비교에 관심이 있었기 때문에 '집에서 만든'테스트입니다.


8

지겐 https://github.com/hughperkins/jeigen

  • 가장 빠른 무료 C ++ 라이브러리 중 하나 인 Eigen C ++ 라이브러리 http://eigen.tuxfamily.org 포장
  • 비교적 간결한 구문, 예 : 'mmul', 'sub'
  • 고밀도 및 희소 행렬 모두 처리

두 개의 고밀도 매트릭스를 곱한 빠른 테스트 :

정적 jeigen.MatrixUtil. * 가져 오기

int K = 100;
int N = 100000;
DenseMatrix A = rand(N, K);
DenseMatrix B = rand(K, N);
Timer timer = new Timer();
DenseMatrix C = B.mmul(A);
timer.printTimeCheckMilliseconds();

결과 :

Jama: 4090 ms
Jblas: 1594 ms
Ojalgo: 2381 ms (using two threads)
Jeigen: 2514 ms
  • 자마에 비해 모든 것이 더 빠릅니다 :-P
  • jigen에 비해 Jeigen은 그리 빠르지는 않지만 희소 행렬을 처리합니다.
  • ojalgo와 비교하여 Jeigen은 경과 시간이 거의 동일하지만 하나의 코어 만 사용하므로 Jeigen은 전체 CPU의 절반을 사용합니다. Jeigen은 더 간결한 구문을 가지고 있습니다.

Jeigen은 굉장해 보인다! 최근에 JNI와 DLL을 사용하여 매우 큰 희소 행렬을 해결하기 위해 Eigen을 Java로 구현했습니다. DLL이있는 내 버전은 테스트 (8000x8000 행렬 이상)의 병렬 콜트보다 20 이상 빠릅니다. 나는 Jeigen에 대해 알고 있었으면 좋겠다!
Z boson

6

몇 가지 다른 하드웨어 구성을 위해 http://code.google.com/p/java-matrix-benchmark/ 에서 Java로 사용할 수있는 다양한 매트릭스 패키지의 벤치 마크가 있습니다. 그러나 자체 벤치 마크를 대신 할 수는 없습니다.

성능은 보유하고있는 하드웨어 유형 (CPU, 코어, 메모리, L1-3 캐시, 버스 속도), 매트릭스 크기 및 사용하려는 알고리즘에 따라 달라질 수 있습니다. 라이브러리마다 알고리즘마다 다른 동시성에 대한 요구가 있으므로 단일 답변이 없습니다. 또한 기본 라이브러리에서 예상 한 형식으로 변환하는 오버 헤드로 인해 사용 사례의 성능 이점이 무효화 될 수 있습니다 (일부 Java 라이브러리에는 추가 성능 최적화에 사용할 수있는 매트릭스 스토리지와 관련하여 더 유연한 옵션이 있음).

일반적으로 JAMA, Jampack 및 COLT는 오래되었으며 선형 대수학에 대해 Java에서 현재 사용 가능한 성능의 상태를 나타내지 않습니다. 보다 현대적인 라이브러리는 다중 코어 및 CPU 캐시를보다 효과적으로 사용합니다. JAMA는 참조 구현이었으며 성능에 거의 영향을 미치지 않으면 서 교과서 알고리즘을 거의 구현합니다. COLT와 IBM Ninja는 기본 라이브러리보다 50 % 뒤쳐져 있어도 Java에서 성능이 가능함을 보여주는 최초의 Java 라이브러리였습니다.


4

나는 ~의 저자입니다 la4j (Linear Algebra for Java) 라이브러리 이며 여기에 내 요점이 있습니다. 3 년 동안 la4j를 작업 해 왔으며 (최신 릴리스는 0.4.0 [2013 년 6 월 1 일]) 이제 최소한의 필수 기능 만 다루었으므로 성능 분석 및 최적화를 시작할 수 있습니다. 그래서 la4j는 내가 원하는만큼 빠르지 않지만 그것을 바꾸는 데 많은 시간을 소비하고 있습니다.

현재 la4j의 새 버전을 JMatBench 플랫폼 으로 이식하는 중입니다 . la4j에서 훨씬 빠른 내부 행렬 형식, 안전하지 않은 접근 자 및 행렬 곱셈을위한 빠른 차단 알고리즘과 같은 몇 가지 개선 사항이 있기 때문에 새 버전이 이전 버전보다 더 나은 성능을 발휘하기를 바랍니다.


1
아니오-la4j는 실제로 경쟁이 없습니다. 참조 code.google.com/p/java-matrix-benchmark
크리스토퍼 매닝에게

많이 바뀌 었습니다. 귀하의 답변 이후 두 가지 버전의 라이브러리를 출시했습니다. 현재 릴리스는 0.4.0입니다. 그리고 그냥 날아갑니다.
블라디미르 코스 튜 코프

3

Pentiums 및 이후 프로세서의 벡터 컴퓨팅 기능 (LAPACK 및 현재 Atlas BLAS와 같은 MMX 확장으로 시작)에 크게 의존하는 Linalg 코드는 "환상적으로 최적화 된"것이 아니라 단순히 업계 표준입니다. Java에서 그 성능을 복제하려면 기본 라이브러리가 필요합니다. 나는 당신이 묘사 한 것과 같은 성능 문제를 겪었으며 (주로 Choleski 분해를 계산할 수 있음) 실제로 효율적인 것을 발견하지 못했습니다 .Jama는 구현자가 따라야 할 템플릿 및 참조 키트이기 때문에 순수한 Java입니다. .. 결코 일어나지 않았다. 아파치 수학의 공통점을 알고 있습니다. COLT는 아직 테스트를 해보았지만 닌자 개선에 크게 의존하는 것 같습니다. 대부분은 애드혹 Java 컴파일러를 구축하여 도달 한 것이므로 도움이 될 것 같지는 않습니다. 그 시점에서 우리는 "


좋은 지적! : JNI와 알파 단계 프로젝트는 아틀라스의 래퍼 jblas.org . 작성자의 블로그 게시물 : mikiobraun.blogspot.com/2008/10/…
dfrankow

3

우리는 꽤 큰 심각한 재무 계산에 COLT를 사용했으며 그 결과에 매우 만족했습니다. 심하게 프로파일 링 된 코드에서 우리는 COLT 구현을 우리의 것으로 대체 할 필요가 거의 없었습니다.

자체 테스트에서 (분명히 독립적이지 않음) 인텔이 직접 최적화 한 어셈블러 루틴의 2 요소 내에서 주장한다고 생각합니다. 잘 사용하는 비결은 디자인 철학을 이해하고 불필요한 객체 할당을 피하는 것입니다.


3

인텔 수학 커널 라이브러리를 살펴 보셨습니까 ? ATLAS 보다 성능이 우수하다고 주장합니다 . MKL은 JNI 래퍼를 통해 Java에서 사용할 수 있습니다 .


2
우리는 그것을 가지고 있습니다. a) 라이센스가 Atlas보다 제한적이므로 모든 컴퓨터를 사용할 수는 없습니다. b) Java가 아닙니다 (그리고 우리가 Java에 있기를 원하는 이유가 있다고 말했듯이).
dfrankow

즉, 이것은 Java 라이브러리에 대한 내 질문에 대한 답변이 아닙니다 (그러나 그것을 공감 할 평판은 없습니다).
dfrankow

@ dfrankow : Java에서 사용하는 것에 대한 귀하의 우려를 해결하기 위해 답변을 업데이트했습니다.
Zach Scrivena

1
+1, 만약 당신이 찾고있는 속도라면, 이것이가는 길인 것 같습니다
Gab Royer

2
마지막 링크가 끊어졌습니다.
gouessej


2

jblas 프로젝트 를 확인하고 싶을 수도 있습니다 . 고성능 매트릭스 작업에 BLAS, LAPACK 및 ATLAS를 사용하는 비교적 새로운 Java 라이브러리입니다.

개발자는 jblas가 MTJ 및 Colt에 유리하게 나오는 벤치 마크 를 게시했습니다 .


2

3d 그래픽스 응용 프로그램의 경우 lwjgl.util 벡터 구현은 위에서 언급 한 jblas보다 약 3 배나 성능이 우수합니다.

4x4 행렬로 vec4에 백만 개의 행렬 곱셈을 수행했습니다.

lwjgl은 약 18ms로 완료되었으며 jblas는 약 60ms가 필요했습니다.

(JNI 접근법은 상대적으로 작은 곱셈의 빠른 연속 적용에는 적합하지 않다고 가정합니다. 변환 / 매핑은 곱셈의 실제 실행보다 시간이 오래 걸릴 수 있기 때문입니다.)


1

고차원 행렬을 많이 만드는 경우 2 차원 배열 대신 단일 차원 배열을 사용하도록 Jama를 변경하면 Jama를 약 20 % 더 빠르게 만들 수 있습니다. Java가 다차원 배열을 효율적으로 지원하지 않기 때문입니다. 즉. 배열 배열을 만듭니다.

콜트는 이미 이것을하고 있지만, 콜트에서는 단순한 기능이 왜 느린 지 설명 할 수있는 자마보다 더 복잡하고 강력하다는 것을 알았습니다.

대답은 실제로 당신이하고있는 것에 달려 있습니다. Jama는 Colt가 할 수있는 일 중 일부를 지원하여 더 많은 차이를 만들지 않습니다.



0

자유롭게 사용할 수있는 다양한 Java 선형 대수 라이브러리가 있습니다. http://www.ujmp.org/java-matrix/benchmark/ 불행하게도이 벤치 마크에서는 행렬 곱셈에 대한 정보 만 제공합니다 (테스트를 바꿈으로써 다른 라이브러리가 각각의 디자인 기능을 이용할 수는 없음).

살펴보아야 할 것은 이러한 선형 대수 라이브러리가 다양한 행렬 분해 계산을 요청받을 때 어떻게 수행되는지입니다. http://ojalgo.org/matrix_compare.html


0

MTJ (Matrix Tookits Java)는 이전에 이미 언급되었지만 다른 사람이이 스레드를 다루는 경우 다시 언급 할 가치가 있습니다. 관심있는 사람들에게는 MTJ가 아파치 커먼즈 math 2.0 의 linalg 라이브러리를 대체하는 것에 대해 이야기하는 것처럼 보이지만 최근에는 어떻게 진행되고 있는지 잘 모르겠습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.