下面的代码运行用户和写入文件的比较。我删除了一些代码以使其尽可能简洁,但速度也是此代码中的一个问题:
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,但在我正在处理的代码中 大小为8000,转换为64'000'000比较。我 使用synchronized块,以便多个线程不写入 同时到同一个文件。考虑到性能提升 在内部循环中填充单独的集合(userList.par.map(yUser =&gt; {) 然后将该集合写成单独的文件。
我是否可以使用其他方法来提高性能。这样我就可以 处理一个包含8000个项目而不是上面100个例子的列表?
答案 0 :(得分:1)
我不确定你是否删除了太多的代码以保持清晰,但从我所看到的,绝对没有什么可以并行运行,因为你唯一要做的就是写一个文件。
编辑:
您应该做的一件事是在同步调用appendToFile之前移动getDistance(...)
计算,否则您的并行化代码最终会顺序执行。
我不是调用同步的appendToFile,而是以非同步方式调用appendToFile,但是每次调用该方法都会将新行添加到某个同步队列中。然后我会有另一个线程定期将该队列刷新到磁盘。但是,您还需要添加一些内容以确保在完成所有计算时刷新队列。所以这可能变得复杂......
或者,您也可以保留代码并简单地删除对appendToFile的调用。看来println itself is synchronized。然而,由于println未正式同步,并且未来版本可能会发生变化,因此存在风险。