程序员大家好.我已经问了一个问题,但是尽管我得到了很好的答案,但我无法解决我的问题.然后,我花时间重构我的代码,以便提高其并行化潜力(通过减少计算批次,每个计算任务更多).但是我仍然无法获得比串行处理更好的性能.
我怀疑这种缓慢的并行处理是由于上下文切换造成的.或者可能是由于常见对象的"自动"同步.我想你可以帮我理解发生了什么.
让我说明一下我的情况:我正在制定一个科学计算程序.它不依赖于外部事物,只取决于我在开始时给它的输入值.这个问题的大小可以通过Ns(我使用的名称)来衡量.它可以被视为解决方案的"分辨率",它是用户输入之一,通常大约为100.
通过这种方式,我在我的主类中有几个双数组,例如double ys[Ns][N]或者phiS[Ns][Nord][N],其中N和Nord是程序的其他固定大小.在我的程序中,我必须为每个Ns点计算几个东西,这就是并行化.每个点计算都是独立的,所以我可以把它们分成不同的线程,希望它变得更快.
因此,for (int i=0; i<Ns; <i++)我没有使用循环,而是将此计算任务划分为Runnable批处理,每个批处理都在较小的区间内进行:for (int i=start; i<end; i++)其中,start和end始终位于0和Ns之间.例如,如果我在双核PC上,我会制作两个批次,一个用start = 0和end = Ns/2,另一个用start = Ns/2和end = Ns.如果我在一个四核,第二批将有start = Ns/4来end = Ns/2等(假设分工精确时间任何情况下).
每个Batch作为实现Runnable的类存储在a中,ArrayList<Batch>并且被赋予FixedThreadPool大小等于核心数的大小.它执行批处理并等待它们使用简单的CountDown方案完成.
各该批次的需要从主类别的节目的访问这些阵列中的数据,但它们的访问使得每个批次仅读取yS[start][]到yS[end][],因此分两批将永远不会尝试读取相同的数组元素.我想知道Java是否仍然锁定了yS,即使每个批次都没有尝试访问与其他元素相同的元素.
我想知道我的问题是否与上下文切换引起的开销有关,因为每个批处理需要处理数千个双打,并且如果构建程序的方式会影响它.
也许我应该找到一种方法来传递给每个批次只是与它相关的数组的元素,但我不知道如何处理它.如果有指针,我可以使用简单的指针操作获得所需元素的新数组,而无需重新分配任何内容.有没有办法在Java中做这样的事情?
好吧,最后,还要提一下:有一部分代码需要同步(它处理其他数组)并且它已经正常工作.我上面描述的计算职责不是我的程序所做的唯一事情.它们位于循环内,与顺序处理部分交替,但作为总执行时间非常重要.
总而言之,问题是:为什么我没有获得多线程,当我期待的时候?
我刚刚在这里运行了几次简单的串行和多线程程序,串行程序为14500 ms,多线程程序为15651 ms.两者都在同一个双核心.其他注意事项:在串行运行中,每个计算任务(从0到Ns)大约需要1.1到4.5 ms.从双线程开始,每批(Ns/2点)大约需要0.5到3毫秒; (从run()方法的顶部到底部测量.每次计算任务因其自身的数值收敛而不同)
非常感谢您的关注.
首先,再次,感谢已经回答了我的问题.我不是一个非常有经验的程序员,这是我第一次使用多线程.
我得到了一个像我的问题一样工作的例子.我希望这可以缓解我们的情况.
public class ThreadMeasuring {
private static final int TASK_TIME = 1; //microseconds
private static class Batch implements Runnable {
CountDownLatch countDown;
public Batch(CountDownLatch countDown) {
this.countDown = countDown;
}
@Override
public void run() {
long t0 =System.nanoTime();
long t = 0;
while(t<TASK_TIME*1e6){ t = System.nanoTime() - t0; }
if(countDown!=null) countDown.countDown();
}
}
public static void main(String[] args) {
ThreadFactory threadFactory = new ThreadFactory() {
int counter = 1;
@Override
public Thread newThread(Runnable r) {
Thread t = new …Run Code Online (Sandbox Code Playgroud) 我正在处理Java中的多线程,正如有人向我指出的那样,我注意到线程正在热身,它们会在反复执行时变得更快.我想了解为什么会发生这种情况,以及它是否与Java本身有关,或者它是否是每个多线程程序的常见行为.
代码(由Peter Lawrey撰写)举例说明如下:
for (int i = 0; i < 20; i++) {
ExecutorService es = Executors.newFixedThreadPool(1);
final double[] d = new double[4 * 1024];
Arrays.fill(d, 1);
final double[] d2 = new double[4 * 1024];
es.submit(new Runnable() {
@Override
public void run() {
// nothing.
}
}).get();
long start = System.nanoTime();
es.submit(new Runnable() {
@Override
public void run() {
synchronized (d) {
System.arraycopy(d, 0, d2, 0, d.length);
}
}
});
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);
// get a the values in d2. …Run Code Online (Sandbox Code Playgroud)