java – 多线程矩阵乘法
我最近开始在java中学习多线程.由于我正在为我的大学编写一个数值计算程序,我决定通过编程多线程矩阵乘法进行一些初步尝试. 这是我的代码.请记住,这只是作为第一次尝试,并不是很干净.
我有两个关于多线程的一般性问题,我希望没有为此开设一个新主题. >有没有办法编写代码而不需要为实现runnable或callable的线程添加其他类?我查看了使用匿名内部类和lambdas的方法,但据我有fount信息,我不能以这种方式将参数传递给线程,因为run()和call()不接受任何,即除非参数是最后的.但是假设我为矩阵运算编写了一个类,我宁愿不为每个想在线程中运行的操作编写一个additinal类. 现在直接告诉我的代码: 我以四种不同的方式实现矩阵乘法,作为在我的主线程中运行的方法,作为在新线程中运行的方法,但仍然没有多线程(以确保我的主线程中不会有任何后台操作减慢它),以及两个多线程矩阵乘法的不同方法.第一个版本转换第二个矩阵,将乘法作为向量 – 向量乘法提交,并将矩阵转换回其原始形式.第二个版本直接采用矩阵,并且另外采用两个索引来定义矢量矢量乘法的矩阵的行和列. 对于所有版本,我测量了乘法所需的时间,并计算了得到的矩阵的平均值,以查看结果是否相同. 我在两台计算机上运行此代码,包括相同的JVM和Windows 10.第一台是我的笔记本电脑,i5第5代,2,6 Ghz双核,第二台是我的台式电脑,i5第4代,4,2 Ghz四核. 我希望我的台式电脑更快.我还期望多线程版本占用了单元线程版本的大约一半/四分之一的时间,但更多的是因为还有额外的工作来创建线程等.最后,我期望第二个多线程版本,它不转置一个矩阵两倍,更快,因为操作较少. 运行代码后,我对结果有点困惑,希望有人能向我解释一下: 对于两种单线程方法,我的笔记本电脑需要大约340s(矩阵大小为3000).所以我假设在我的主线程中没有完成昂贵的后台任务.另一方面,我的桌面PC需要440s.现在的问题是,为什么我的笔记本电脑速度更快,速度更快?即使第五代比第四代更快,因为我的台式电脑以我的笔记本电脑的速度运行1.6倍,我仍然期望它更快.这些世代之间的差异不太大. 对于多线程方法,我的笔记本电脑需要大约34秒.如果多线程是完美的,那么它不应该少于一半.为什么它在两个线程上快十倍?我的台式电脑也是如此.使用四个线程,乘法在16s而不是440s完成.这就像我的桌面PC工作速度与我的笔记本电脑相同,只有四个而不是两个线程. 现在,对于两个多线程方法之间的比较,两次转换一个矩阵的版本在我的笔记本电脑上花费大约34秒,直接占用矩阵的版本大约需要200秒.这听起来很现实,因为它超过单线程方法的一半.但为什么它比第一个版本慢得多?我会假设两次转置矩阵比获取矩阵元素的额外时间慢?有没有我缺少的东西或使用矩阵真的比使用矢量慢得多? 我希望有人能回答这些问题.很抱歉写这么长的帖子. 此致 最佳答案
这个问题的答案很明显:矩阵乘法所需的时间主要是将数据从RAM移动到CPU缓存所花费的时间.您可能有4个内核,但只有1个RAM总线,因此如果它们都相互阻塞等待内存访问,则使用更多内核(多线程)将无法获得任何好处.
您应该尝试的第一个实验是:使用矩阵转置和向量乘法编写单线程版本.你会发现它的速度要快得多 – 可能与转置的多线程版本一样快. 原始单线程版本之所以如此之慢,是因为它必须为列中的每个单元格加载一个缓存块.如果使用矩阵转置,则所有这些单元格在内存中是顺序的,加载一个块会获得一堆它们. 因此,如果您想优化矩阵乘法,FIRST优化内存访问以提高缓存效率,那么就可以在几个线程之间划分工作 – 不超过核心数量的两倍.更多的东西只是浪费时间和资源与上下文切换等. 关于你的其他问题: 1)使用lambdas可以方便地从创建它们的范围中捕获变量,例如:
2)GC将负责处理.您不需要显式关闭线程池以释放任何资源. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |