我正在编写一个使用Executorservice框架处理矩阵并行编程的程序。并且我将fixedpoolsize设置为4,但是令我惊讶的是,当矩阵维数设置为5000时,对串行执行使用多线程的加速大于4(这也是我的CPU内核)。而且我已经检查过我的CPU不支持超线程。
实际上,我使用Callable and Future容器,因为我的多线程任务要求返回结果。
// Part of code for parallel programming
double[][] x = new double[N][N];
List<Future<double[]>> futureList = new ArrayList<>();
for (int k=0;k<N;k++)
{
Future<double[]>temp=service.submit(new Thread.Task(N,k,matrix,vector));
futureList.add(temp);
}
for (int j = 0; j < N; j++) {
x[j]=futureList.get(j).get();
}
public double[] call() throws Exception {
for (int i = N - 1; i >= 0; i--)
{
double sum = 0;
for (int j = i + 1; j < N; j++)
{
sum += matrix[i][j] * x[j];
}
x[i] = (vector[i][k] - sum) / matrix[i][i];
}
return x;
}
// Part of code for Serial programming
double[][] x = new double[N][N];
for (int k=0;k<N;k++)
{
for (int i = N - 1; i >= 0; i--)
{
double sum = 0;
for (int j = i + 1; j < N; j++)
{
sum += matrix[i][j] * x[j][k];
}
x[i][k] = (vector[i][k] - sum) / matrix[i][i];
}
}
总之,我只是将内部循环带走,让它由线程运行,而使外部循环保持不变。
但是加速如何这样?
由于我以前的概念,最大加速只能是4。并且我已经检查过该任务实际上是由4个线程完成的。
可以在同一个CPU上使用线程。您不需要多核处理器即可执行多线程应用程序。
将线程视为一个小进程,它由父程序创建并在完成后销毁。甚至单台cpu计算机也可以一次运行多个线程。
[ExecutorService
调度要执行的线程,并将运行与包括内核在内的可用资源一样多的并行线程。
这里是fixedThreadPool
上的文档
public static ExecutorService newFixedThreadPool(int nThreads)
创建一个线程池,该线程池可重用固定数量的操作线程共享无界队列。在任何时候,最多nThreads个线程将是活动的处理任务。如果提交了其他任务当所有线程都处于活动状态时,它们将在队列中等待,直到线程可用。如果在执行期间由于失败导致任何线程终止在关机之前执行,如果需要,将替换一个新的执行后续任务。池中的线程将一直存在,直到它被明确关闭
您也可以尝试workStealingPool
public static ExecutorService newWorkStealingPool()
创建一个使用所有可用处理器作为目标的工作窃取线程池并行度。
这可能是CPU缓存关联性的影响。如果每个核心处理问题的不同部分,则可以在缓存使用方面实现更高的效率。由于RAM的速度比高速缓存慢10倍或更多倍,因此差异可能很大。