Vì vậy, về cơ bản, bạn muốn mã của mình chạy nhanh hơn. JNI là câu trả lời. Tôi biết bạn đã nói điều đó không hiệu quả với bạn, nhưng hãy để tôi cho bạn thấy rằng bạn đã sai.
Đây là Dot.java
:
import java.nio.FloatBuffer;
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;
@Platform(include = "Dot.h", compiler = "fastfpu")
public class Dot {
static { Loader.load(); }
static float[] a = new float[50], b = new float[50];
static float dot() {
float sum = 0;
for (int i = 0; i < 50; i++) {
sum += a[i]*b[i];
}
return sum;
}
static native @MemberGetter FloatPointer ac();
static native @MemberGetter FloatPointer bc();
static native @NoException float dotc();
public static void main(String[] args) {
FloatBuffer ab = ac().capacity(50).asBuffer();
FloatBuffer bb = bc().capacity(50).asBuffer();
for (int i = 0; i < 10000000; i++) {
a[i%50] = b[i%50] = dot();
float sum = dotc();
ab.put(i%50, sum);
bb.put(i%50, sum);
}
long t1 = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
a[i%50] = b[i%50] = dot();
}
long t2 = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
float sum = dotc();
ab.put(i%50, sum);
bb.put(i%50, sum);
}
long t3 = System.nanoTime();
System.out.println("dot(): " + (t2 - t1)/10000000 + " ns");
System.out.println("dotc(): " + (t3 - t2)/10000000 + " ns");
}
}
và Dot.h
:
float ac[50], bc[50];
inline float dotc() {
float sum = 0;
for (int i = 0; i < 50; i++) {
sum += ac[i]*bc[i];
}
return sum;
}
Chúng tôi có thể biên dịch và chạy nó với JavaCPP bằng lệnh này:
$ java -jar javacpp.jar Dot.java -exec
Với CPU Intel (R) Core (TM) i7-7700HQ @ 2,80GHz, Fedora 30, GCC 9.1.1 và OpenJDK 8 hoặc 11, tôi nhận được loại đầu ra này:
dot(): 39 ns
dotc(): 16 ns
Hoặc nhanh hơn khoảng 2,4 lần. Chúng ta cần sử dụng bộ đệm NIO trực tiếp thay vì mảng, nhưng HotSpot có thể truy cập bộ đệm NIO trực tiếp nhanh như mảng . Mặt khác, việc mở vòng lặp theo cách thủ công không mang lại hiệu suất tăng có thể đo lường được, trong trường hợp này.
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:+LogCompilation
. Bạn sẽ cần một chương trình chạy phương thức vectorizable đủ số lần để làm cho nó "nóng".