Java多线程:性能测试
我在LinuxUbuntu18.04下有一个16核的Ryzen处理器,我想用java线程测试它。我对演出有点失望。我的期望是parralel的计算速度要快得多,但只有1秒+几毫秒的差异 那么,假设我的线程不受多个内核的支持?我的小测试不使用任何同步。它只是计算每个矩阵元素。是否有任何jvm优化,或者我需要一些参数来运行java程序 以下是我的资料来源:Java多线程:性能测试,java,multithreading,Java,Multithreading,我在LinuxUbuntu18.04下有一个16核的Ryzen处理器,我想用java线程测试它。我对演出有点失望。我的期望是parralel的计算速度要快得多,但只有1秒+几毫秒的差异 那么,假设我的线程不受多个内核的支持?我的小测试不使用任何同步。它只是计算每个矩阵元素。是否有任何jvm优化,或者我需要一些参数来运行java程序 以下是我的资料来源: public class Image2DInput <T> { public static Integer[] dimensi
public class Image2DInput <T> {
public static Integer[] dimension(Integer d0, Integer d1) {
return new Integer[] {d0, d1};
}
public static Integer[] point(Integer i, Integer j) {
return new Integer[] {i, j};
}
public static <T> T origin(T origin) {
return origin;
}
private final T origin;
private final BiFunction<Integer[], T, T> delta;
private final Object[][] matrix;
public Image2DInput(
Integer[] dimension,
T origin,
BiFunction<Integer[], T, T> delta)
{
throwIfNull(dimension, "origin must not be null");
throwIfNull(origin, "origin must not be null");
throwIfNull(delta, "deltaFunction must not be null");
this.origin = origin;
this.delta = delta;
this.matrix = new Object[dimension[0]][dimension[1]];
if (dimension[0] > 0 && dimension[1] > 0) {
setMatrix();
setOrigin();
}
}
private void setOrigin () {
var d0 = matrix.length / 2;
var d1 = matrix[0].length / 2;
this.matrix[d0][d1] = origin;
}
private void setMatrix () {
var numberOfThreads = Runtime.getRuntime().availableProcessors();
var threads = IntStream
.range(0, numberOfThreads)
.mapToObj( index -> new RowWorker(index, numberOfThreads) )
.collect(Collectors.toList());
threads.stream().forEach( t -> t.start() );
threads.stream().forEach( t -> join(t) );
}
private void setSingleThreadedMatrix () {
for (var i=0; i<matrix.length; ++i)
for (var j=0; j<matrix[0].length; ++j)
matrix[i][j] = delta.apply(new Integer[]{i,j}, origin);
}
private class RowWorker extends Thread {
private Integer id;
private Integer offset;
RowWorker(Integer id, Integer offset) {
this.id = id;
this.offset = offset;
setPriority(Thread.MAX_PRIORITY);
}
@Override
public void run () {
for (var i=id; i<matrix.length; i+=offset)
for (var j=0; j<matrix[0].length; ++j)
matrix[i][j] = delta.apply(new Integer[]{i,j}, origin);
}
}
@Override
public String toString () {
var image = new StringBuilder();
for (var i=0; i<matrix.length; ++i)
writeRow (i, image);
return image.toString();
}
private void writeRow (int i, StringBuilder image) {
for (var j=0; j<matrix[0].length; ++j)
image.append(at(i,j)).append(", ");
image.replace(image.length()-2, image.length(), "\n");
}
private T at(int i, int j) {
return (T) matrix[i][j];
}
}
下面是我的测试运行:
@Test
public void testPerformance () {
final var dim = dimension(4*2560,4*1440);
complexImage(dim, z(0.0,0.0), (p,o) -> compute(dim, p, o));
}
private Complex compute (Integer[] dim, Integer[] pt, Complex origin) {
var originAt = point(dim[0] /2, dim[1] /2);
var offset = 1.0;
return
z( (pt[1]-originAt[1])*offset, -(pt[0]-originAt[0])*offset )
.add(origin);
}
private String complexImage (
Integer[] dimension,
Complex origin,
BiFunction<Integer[], Complex, Complex> delta)
{
var image = new Image2DInput<Complex>(dimension, origin, delta);
return image.toString();
}
我已更改为FixedThreadPool。我看不出有什么不同
private void setMatrix () {
var numberOfThreads = Runtime.getRuntime().availableProcessors();
var service = Executors.newFixedThreadPool(numberOfThreads);
IntStream
.range(0, numberOfThreads)
.forEach( id -> service.submit( () -> {
for (var i=id; i<matrix.length; i+=numberOfThreads)
for (var j=0; j<matrix[0].length; ++j)
matrix[i][j] = delta.apply(new Integer[]{i,j}, origin);
} ));
try {
service.shutdown();
service.awaitTermination(60, TimeUnit.SECONDS);
} catch (Exception ex) {}
}
这段代码看起来效率非常低,例如,在“性能”代码中不应该看到新的整数[],而且还缺少预热和合理的计时。我不认为这些基准特别有用。我强烈怀疑您正在计时的是32个线程的创建。同意Boris的观点,线程初始化是昂贵的,最好通过java.util.concurrent.ExecutorsNewfixedThreadPool使用线程池,并在run methodsInteger中计算时间?这不是由编译器优化的吗?我用它是出于一般的原因。。。我用then代替FixedThreadPool,得到了相同的结果。16个线程比单线程快一秒?顺便提一下我删除了toString方法调用。再快一秒钟也没什么意义。重要的是时间随着什么因素变化。如果一秒钟对应于16的加速系数,那就太大了。如果它比这个小得多,那就不算大了。然而,我猜您的算法是内存有限的,几乎所有的时间都花在访问内存上。因此,当您并行化它时,您不会看到任何显著的性能改进。谢谢您的提示。是的,它被限制在记忆中。线程一直在向矩阵写入数据。有更好的方法吗?比如,先计算,然后在计算之后,立即写入内存?