2009-11-09 47 views
6

Tôi tò mò về hiệu suất của thuật toán số Java, ví dụ phép nhân ma trận nhân đôi ma trận, sử dụng các máy JIT mới nhất so với ví dụ để điều chỉnh SSE C++/assembler hoặc Fortran.Hiệu suất Java trong thuật toán số

Tôi đã xem trên web nhưng hầu hết các kết quả đến từ gần 10 năm trước và tôi hiểu rằng Java đã phát triển khá nhiều kể từ đó.

Nếu bạn có kinh nghiệm sử dụng Java cho các ứng dụng có số lượng lớn, bạn có thể chia sẻ kinh nghiệm của mình. Ngoài ra Java hoạt động tốt như thế nào trong các hạt nhân mà các vòng lặp tương đối ngắn và truy cập bộ nhớ không đồng nhất nhưng vẫn nằm trong giới hạn của bộ đệm L1? Nếu hạt nhân đó được thực hiện nhiều lần liên tiếp, JVM có thể tối ưu hóa nó trong suốt thời gian chạy không?

Cảm ơn

+3

Đặt cược tốt nhất của bạn là tự mình thử nghiệm, khi so sánh với C++ sẽ khó khăn vì đó sẽ là nhanh nhất và mọi so sánh sẽ không có quyền truy cập vào triển khai cụ thể của bạn. –

+1

Lưu ý những người khác đến trang này: câu hỏi này và phần lớn các câu trả lời là từ năm 2009. JVM tốt hơn rất nhiều so với trước đây. – eis

+0

Bạn có thể muốn xem ND4J, hỗ trợ mảng n chiều cho Java. http://nd4j.org/benchmarking.html – tremstat

Trả lời

-4

Java sử dụng một trình biên dịch Just in Time (JIT) để chuyển đổi bytecode sang ngôn ngữ máy có nguồn gốc - vì vậy lần đầu tiên nó chạy qua một khối mã nó sẽ chậm hơn nhưng một khi phân khúc này là 'ấm lên 'hiệu suất sẽ tương đương. Tóm lại - hiệu suất số là khá tốt.

+1

JIT là tốt, nhưng không đủ để đảm bảo hiệu suất số tốt. –

0

Thứ hai là đặt cược tốt nhất của bạn là tự kiểm tra, vì hiệu suất sẽ thay đổi đôi chút tùy thuộc vào những gì bạn đang làm chính xác. Tôi cảm thấy khó tin rằng câu trả lời của Shane C. Mason rằng hiệu năng Java sẽ giống như hiệu năng C++ hoặc Fortran, thậm chí C++ và Fortran không thực sự so sánh được với một số thuật toán máy tính khoa học.

Tôi có một mã động lực học chất lỏng mà tôi đã viết bằng cách sử dụng C++ và cùng một mã cơ bản được dịch sang Fortran. Tôi không thực sự chắc chắn tại sao, nhưng phiên bản Fortran nhanh hơn gấp hai lần so với phiên bản C++. Tôi đoán rằng với các tính năng như kiểm tra giới hạn và thu gom rác, Java sẽ chậm hơn cả hai, nhưng tôi sẽ không biết cho đến khi tôi thử nghiệm.

+0

bạn có sử dụng từ khóa hạn chế trong mã C++ không? Trình biên dịch Fortran không phải đảm bảo rằng các con trỏ bộ nhớ không được đặt bí danh trong khi trình biên dịch C++ phải giả định rằng bộ nhớ được đặt bí danh trừ khi được nói cách khác. bạn đã sử dụng trình biên dịch nào? Tôi lập trình chương trình của tôi trong C + + với nội tại và trình biên dịch Intel nhanh hơn đáng kể so với GCC, tôi đoán lệnh C++ của Intel tốt hơn vì việc lắp ráp cũng rất giống nhau ngoại trừ việc đặt hàng. – Anycorn

+0

Tôi đang mơ hồ nhận thức được các vấn đề về răng cưa, nhưng tôi vẫn chưa hiểu rõ vấn đề này. Tôi đã không cố gắng hạn chế được nêu ra, tôi không có thời gian để chi tiêu về điều này, không may. Tôi đã sử dụng icpc và ifort (cả hai trình biên dịch Intel) trên Linux với -O3. Lưu ý rằng điểm của tôi không phải là hiệu suất C++ không thể khớp với fortran, mà đúng hơn là bạn cần phải so sánh các triển khai ngoài các ngôn ngữ. – notJim

+0

Fortran cũng có mô hình số học thoải mái hơn nhiều so với C++ - nó được phép thực hiện rất nhiều tối ưu hóa toán học skanky theo mặc định mà bạn chỉ nhận được trong C/C++ với -ffast-math và tương tự. Đôi khi điều này không quan trọng, và đôi khi nó sẽ làm cho kết quả của bạn kém chính xác hơn. –

1

This là liên kết đến trang chiêu thức ngôn ngữ lập trình cho java so với C++, sẽ cho bạn so sánh tốc độ của java trên một số thuật toán chuyên sâu tính toán. Nó cũng sẽ cho bạn thấy mã java hiệu năng cao nhất trông như thế nào. Đối với hầu hết các phần, đối với một vài tiêu chuẩn cụ thể, java mất nhiều thời gian hơn (nhưng không nhiều hơn 2 hoặc 3 lần) để chạy.

+0

Tôi không thể ngay lập tức cho biết - không so sánh này bỏ qua lần hâm nóng. Java vẫn cần một _lot_ của công việc ban đầu trước khi đạt tốc độ hành trình. –

+0

đúng. nếu bạn muốn viết một chương trình khởi động, thực hiện một vài phép tính và sau đó tắt, bạn có thể không muốn java. nhưng nếu chương trình của bạn sẽ chạy trong vài phút, thì thời gian khởi động chỉ là tiếng ồn. Một thay thế của khóa học là để bắt đầu một quá trình java và có nó hoạt động như một máy chủ tính toán - mỗi khi bạn cần một phép tính, bạn chỉ cần gọi vào một trường hợp đã chạy. –

+0

@ Thorbjørn Ravn Andersen - 1) Đọc câu hỏi thường gặp! 2) Chú ý các chương trình chạy trong vài giây không phải là micro giây! 3) Xem xét các xấp xỉ trạng thái ổn định http://shootout.alioth.debian.org/u64q/benchmark.php?test=all&lang=javasteady&lang2=gpp&box=1 4) Đọc Câu hỏi thường gặp! về Java http://shootout.alioth.debian.org/u64q/faq.php#dynamic – igouy

1

Điều này đến từ phía .NET, nhưng tôi chắc chắn 90% cũng là trường hợp đối với Java. Trong khi JIT sẽ sử dụng một số lệnh SSE ở nơi có thể, nó hiện không tự động mã hóa mã của bạn khi xử lý, ví dụ, phép nhân ma trận. Hand vectorized C++ sử dụng trình biên dịch nội tại/lắp ráp nội tuyến chắc chắn sẽ nhanh hơn ở đây.

0

Điều này có thể phụ thuộc vào những gì bạn đang làm trong mã C++.

Ví dụ: bạn có đang sử dụng GPU không? Chỉnh sửa Tôi quên về jogl, vì vậy Java có thể cạnh tranh ở đây.

Bạn có song song sử dụng STM hoặc bộ nhớ dùng chung, khi đó Java không thể cạnh tranh được. Để có liên kết phân tích phép nhân song song: http://www.cs.utexas.edu/users/plapack/papers/ipps98/ipps98.html

Bạn có đủ bộ nhớ để thực hiện các phép tính trong bộ nhớ, không cần phải thu gom rác. ? Sau đó, Java có thể cạnh tranh, có lẽ.

Bạn có đang sử dụng đa lõi và C++ được tối ưu hóa để tận dụng lợi thế của kiến ​​trúc này không? Sau đó, Java sẽ không thể cạnh tranh được.

Bạn đang sử dụng một số máy tính được kết hợp với nhau, sau đó Java sẽ không thể cạnh tranh được.

Bạn có sử dụng bất kỳ kết hợp nào trong số này hay không, sau đó nó sẽ phụ thuộc vào việc triển khai cụ thể.

Java không được thiết kế để cạnh tranh với chương trình C++ được điều chỉnh bằng tay, nhưng, thời gian cần để thực hiện việc điều chỉnh, bạn có đang tính toán đủ nơi nó sẽ quan trọng không? Java sẽ có thể cung cấp cho một số tốc độ hợp lý nhưng với công việc ít hơn so với điều chỉnh bằng tay, nhưng không có nhiều cải tiến hơn là chỉ làm mã C++.

Bạn có thể muốn xem liệu có cải tiến nào so với Haskell hay Erlang, ví dụ, trên C++ của bạn, vì các ngôn ngữ này được thiết kế tốt hơn cho loại công việc này.

+0

Sử dụng GPU? Như trong, sử dụng OpenGL? Nếu sử dụng Java JOGL có thể cạnh tranh độc đáo. –

+0

Bạn đã chính xác, tôi đã sửa chữa câu trả lời của tôi, tôi quên rằng bạn có thể sử dụng jogl cho công việc GPU. –

1

Một trong những điểm yếu nhất trong java là các hoạt động ma trận (bản địa). Điều này là do bản chất của ma trận Java:

  • Bạn không thể tuyên bố một ma trận là hình chữ nhật, tức là. mỗi hàng có thể có một số cột khác nhau.

  • Ma trận về mặt kỹ thuật không phải là "ma trận đôi (hoặc int, ...)", mà là một mảng các mảng .... Điểm khác biệt lớn nhất là vì các mảng là các đối tượng Java, bạn có thể gán cùng một đối tượng mảng cho nhiều hơn 1 hàng.

Hai thuộc tính này tạo ra rất nhiều tối ưu hóa ma trận chuẩn không thể cho trình biên dịch.

Bạn có thể nhận được hiệu suất tốt hơn bằng cách sử dụng thư viện Java mô phỏng ma trận trên một mảng dài. Tuy nhiên, bạn có phí gọi phương thức cho tất cả các truy cập.

+2

Tôi nghĩ bạn có nghĩa là bạn không thể khai báo một mảng 2D thành hình chữ nhật. Nhưng bạn dường như đang tranh luận rằng việc thực hiện một cách đơn giản và đơn giản nhất của một ma trận trong Java có một số vấn đề. Tại sao điều này sẽ là triển khai duy nhất có thể? Nếu nó không phải là sau đó không có nhiều của một tuyên bố có thể ở đây về 'bản chất của ma trận Java'. Còn thư viện ma trận Java như Colt thì sao? –

+0

Ma trận không phải lúc nào cũng đại diện theo cách đó. Xem 'java.awt.image.Kernel' cho một ví dụ về ma trận được biểu diễn bằng mảng 1D – finnw

+0

Vấn đề với các thư viện đó là tất cả truy cập ma trận được thực hiện thông qua các phương thức. Các cuộc gọi phương thức chậm hơn so với truy cập mảng nói chung và chúng ngăn chặn tối ưu hóa trình biên dịch nhất định. Ví dụ. 'cho (int i = 0; i Carsten

1

C++ chắc chắn sẽ nhanh hơn. Bạn thậm chí có thể có một số thư viện được tối ưu hóa bằng tay cho mục đích của bạn có chứa mã lắp ráp cho mỗi CPU chính ở ngoài đó. Bạn không thể tốt hơn thế.

Sau đó, bạn có thể sử dụng JNI để gọi nó từ Java, nếu cần.

Java không có nghĩa là tính toán số học hiệu suất cao như thế này. Nếu bạn phụ thuộc vào những điều này, tôi khuyên bạn nên chọn một ngôn ngữ cấp thấp phù hợp để thực hiện điều đó. Hoặc, cách khác, bạn có thể viết phần hiệu năng cụ thể bằng ngôn ngữ cấp thấp, sau đó kết nối nó với giao diện người dùng Java bằng cách sử dụng JNI hoặc một số phương thức IPC khác.

0

Là những loại tính toán mà bạn quan tâm - Chuyển đổi Fourier nhanh, Jacobi thành công hơn thư giãn, tích hợp Monte Carlo, ma trận thưa thớt Mult, Hệ số ma trận LU dày đặc?

Chúng tạo thành SciMark 2.0 composite benchmark mà bạn có thể khởi chạy dưới dạng một applet trên máy của mình.

Ngoài ra còn có ANSI C versions của chương trình và Intel document (pdf) on optimizing and recompiling SciMark for C++.


Tương tự bạn có thể sử dụng The Java Grande Forum Benchmark Suitethe comparison C programs.

2

Tôi đã viết một số mã số nhạy cảm hợp lý và hiệu suất lớn trong Java (crunching mảng lớn của đôi thường).

Tôi đã tìm thấy Java là "đủ tốt" để tính toán số nhanh. Đặc biệt là khi bạn xem xét rằng bạn thường không phải là CPU-ràng buộc anyway - độ trễ bộ nhớ và nhận thức bộ nhớ cache có lẽ sẽ là vấn đề lớn nhất của bạn cho datasets lớn.

Tuy nhiên, bạn vẫn có thể đánh bại Java bằng mã C/C++ được tối ưu hóa bằng tay để tận dụng các hướng dẫn cụ thể hóa vector hoặc bố cục bộ nhớ được tùy chỉnh cao. Vì vậy, đối với mã rất nhanh nhất, bạn có thể xem xét viết các thuật toán cốt lõi trong C/C++ và gọi nó từ Java bằng cách sử dụng JNI.

Cá nhân, tôi thấy rằng việc tạo ra một sự phụ thuộc mã nguồn gốc thường là nhiều rắc rối hơn nó đáng để tôi có xu hướng gắn bó với cách tiếp cận thuần Java.