我正在编写一个在Nehalem处理器上运行的多线程java应用程序.但是我有一个问题,从4个线程开始我几乎没有看到我的应用程序的加速.

我做了一些简单的测试.我创建了一个线程,它只分配一个大数组并访问数组中的随机条目.因此,当我运行多个线程时,运行时间不应该改变(假设我没有超过可用CPU核心数).但我观察到的是,运行1或2个线程的时间几乎相同,但运行4或8个线程的速度要慢得多.所以在尝试解决我的应用程序中的算法和同步问题之前,我想找出什么是我可以实现的最大可能的并行化.

我使用了-XX:UseNUMA JVM选项,因此数组应该在相应线程附近的内存中分配.

附:如果线程正在进行简单的数学计算,则4个甚至8个线程没有时间丢失,所以我得出结论,当线程访问内存时,我遇到了一些问题.


任何帮助或想法都表示赞赏,谢谢.

编辑

谢谢大家的回复.我看到我没有足够好地解释自己.

在尝试消除我的应用程序中的同步问题之前,我做了一个简单的测试,检查可以实现的最佳并行化.代码如下:

public class TestMultiThreadingArrayAccess {
    private final static int arrSize = 40000000;

    private class SimpleLoop extends Thread {
        public void run() {
            int array[] = new int[arrSize];
            for (long i = 0; i < arrSize * 10; i++) {
                array[(int) ((i * i) % arrSize)]++; // randomize a bit the access to the array
            }
            long sum = 0;
            for (int i = 0; i < arrSize; i++)
                sum += array[i];
        }
    }

    public static void main(String[] args) {
        TestMultiThreadingArrayAccess test = new TestMultiThreadingArrayAccess();
        for (int threadsNumber : new int[] { 1, 2, 4, 8 }) {
            Statistics timer = new Statistics("Executing " + threadsNumber+ " threads"); // Statistics is a simple helper class that measures the times
            timer.start();
            test.doTest(threadsNumber);
            timer.stop();
            System.out.println(timer.toString());
        }
    }

    public void doTest(int threadsNumber) {
        Thread threads[] = new Thread[threadsNumber];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new SimpleLoop();
            threads[i].start();
        }

        for (int i = 0; i < threads.length; i++)
            try {
                threads[i].join();
            } catch (InterruptedException e) {
            };
    }
}

因此,您可以看到在这个minitest中根本没有同步,并且数组的分配也在线程中,因此它应该放在可以快速访问的内存块中.此代码中也没有内存争用.仍有4个线程的运行时间下降了30%,8个线程运行速度慢了两倍.当你从代码中我只是等到所有线程完成他们的工作,并且因为他们的工作是独立的线程数不应该影响执行所花费的总时间.

在机器上安装了2个四核超线程Nehalem处理器(共16个CPU),所以有8个线程,每个都可以专门捕获它的CPU.

当我尝试使用较小的数组(20K条目)运行此测试时,4个线程的执行时间的下降为7%,8个线程 – 14%,这是令人满意的.但是当我尝试在大型阵列(40M条目)上随机访问时,运行时间会急剧增加,所以我认为存在大块内存(因为它们不适合高速缓存存储器?)的问题是在非 – 有效的方式.

有什么想法如何解决这个问题?

希望这能以更好的方式澄清问题,再次感谢.

解决方法:

测试中的瓶颈是cpu到内存带宽.即使本地内存可用,它也会被一些线程共享. (内存是节点的本地存储器,而不是特定内核.)一旦CPU可以轻松超过上述测试之类的简单循环的可用带宽,因此在这种测试中增加线程不会提高性能,并且会恶化性能由于缓存一致性恶化.

只是一个完整性测试,您是否也使用并行收集器? -XX:UseParallelGC. UseNUMA只在那时生效.

标签: java, memory-management, multithreading, nehalem

相关文章推荐

添加新评论,含*的栏目为必填