下面的代码比较了用户和写入文件的情况。我删除了一些代码以使其尽可能简洁,但速度也是此代码中的一个问题:
import scala.collection.JavaConversions._
object writedata {
def getDistance(str1: String, str2: String) = {
val zipped = str1.zip(str2)
val numberOfEqualSequences = zipped.count(_ == ('1', '1')) * 2
val p = zipped.count(_ == ('1', '1')).toFloat * 2
val q = zipped.count(_ == ('1', '0')).toFloat * 2
val r = zipped.count(_ == ('0', '1')).toFloat * 2
val s = zipped.count(_ == ('0', '0')).toFloat * 2
(q + r) / (p + q + r)
} //> getDistance: (str1: String, str2: String)Float
case class UserObj(id: String, nCoordinate: String)
val userList = new java.util.ArrayList[UserObj] //> userList : java.util.ArrayList[writedata.UserObj] = []
for (a <- 1 to 100) {
userList.add(new UserObj("2", "101010"))
}
def using[A <: { def close(): Unit }, B](param: A)(f: A => B): B =
try { f(param) } finally { param.close() } //> using: [A <: AnyRef{def close(): Unit}, B](param: A)(f: A => B)B
def appendToFile(fileName: String, textData: String) =
using(new java.io.FileWriter(fileName, true)) {
fileWriter =>
using(new java.io.PrintWriter(fileWriter)) {
printWriter => printWriter.println(textData)
}
} //> appendToFile: (fileName: String, textData: String)Unit
var counter = 0; //> counter : Int = 0
for (xUser <- userList.par) {
userList.par.map(yUser => {
if (!xUser.id.isEmpty && !yUser.id.isEmpty)
synchronized {
appendToFile("c:\\data-files\\test.txt", getDistance(xUser.nCoordinate , yUser.nCoordinate).toString)
}
})
}
}上面的代码以前是一个命令式解决方案,所以.par功能在一个内部和外部循环中。我正在尝试将其转换为功能更强大的实现,同时还利用了Scala的并行集合框架。
在本例中,数据集大小是10,但是在代码中,im处理的大小是8000,这转换为64'000'000个比较。我使用了一个同步的块,这样多个线程就不会同时写入同一个文件。im考虑的一个性能改进是在内部循环( userList.par.map(yUser => {) )中填充一个单独的集合,然后将该集合写出到单独的文件中。
我还可以使用其他方法来提高性能吗?这样我就可以处理一个包含8000个项目的列表,而不是上面100个项目的例子。
发布于 2014-04-11 06:36:11
我不确定你是否为了清晰而删除了太多的代码,但在我看来,绝对没有什么可以并行运行的,因为你唯一要做的就是写入文件。
编辑:
您应该做的一件事是将getDistance(...)计算移到对appendToFile的同步调用之前,否则您的并行化代码最终将是顺序的。
我不会调用同步appendToFile,而是以非同步方式调用appendToFile,但每次调用该方法时都会将新行添加到某个同步队列中。然后,我将有另一个线程定期将该队列刷新到磁盘。但是,您还需要添加一些内容,以确保当所有计算完成时,队列也会被刷新。所以这可能会变得很复杂。
或者,您也可以保留您的代码,简单地删除与appendToFile调用相关的同步。看来println itself is synchronized. .。然而,这将是有风险的,因为println不是正式同步的,它可能会在未来的版本中发生变化。
https://stackoverflow.com/questions/22998596
复制相似问题