2013-07-25 33 views
12

Trong Scala trước 2.10, tôi có thể đặt song song trong defaultForkJoinPool (như trong câu trả lời scala parallel collections degree of parallelism). Trong Scala 2.10, API đó không còn tồn tại nữa. Nó cũng được ghi lại rằng chúng ta có thể thiết lập song song trên một bộ sưu tập đơn (http://docs.scala-lang.org/overviews/parallel-collections/configuration.html) bằng cách gán cho thuộc tính taskSupport của nó.Làm cách nào để đặt số chuỗi mặc định cho bộ sưu tập song song Scala 2.10?

Tuy nhiên, tôi sử dụng các bộ sưu tập song song trên tất cả mã nguồn của mình và không muốn thêm hai dòng bổ sung vào mỗi lần khởi tạo bộ sưu tập đơn lẻ. Có cách nào để cấu hình kích thước pool mặc định toàn cầu mặc định để someCollection.par.map(f(_)) tự động sử dụng số lượng các chuỗi mặc định?

+1

Đây là một chút trên đầu của tôi, nhưng nhìn vào mã nguồn scala tôi nhận thấy một cái gì đó ... có vẻ như các bộ sưu tập song song cơ sở của họ tạo trên "defaultTaskSupport", mà tôi không nhìn thấy một cách để ghi đè bởi vì nó là một đối tượng Val. https://github.com/scala/scala/blob/v2.10.2/src/library/scala/collection/parallel/package.scala – LaloInDublin

Trả lời

14

Tôi biết rằng câu hỏi đã quá một tháng, nhưng tôi đã có chính xác cùng một câu hỏi. Googling là không hữu ích và tôi không thể tìm thấy bất cứ điều gì mà nhìn nửa chừng sane trong API mới.

Thiết lập -Dscala.concurrent.context.maxThreads = n như được đề xuất ở đây: Set the parallelism level for all collections in Scala 2.10? dường như không có tác dụng gì cả, nhưng tôi không chắc liệu tôi có sử dụng đúng cách không (tôi chạy ứng dụng của mình bằng 'java' trong môi trường mà không có 'scala' được cài đặt một cách rõ ràng, nó có thể là nguyên nhân).

Tôi không biết tại sao scala-people đã xóa bộ đặt thiết yếu này khỏi đối tượng gói thích hợp.

Tuy nhiên, nó thường có thể sử dụng phản ánh để làm việc xung quanh một giao diện đầy đủ/lạ:

def setParallelismGlobally(numThreads: Int): Unit = { 
    val parPkgObj = scala.collection.parallel.`package` 
    val defaultTaskSupportField = parPkgObj.getClass.getDeclaredFields.find{ 
    _.getName == "defaultTaskSupport" 
    }.get 

    defaultTaskSupportField.setAccessible(true) 
    defaultTaskSupportField.set(
    parPkgObj, 
    new scala.collection.parallel.ForkJoinTaskSupport(
     new scala.concurrent.forkjoin.ForkJoinPool(numThreads) 
    ) 
) 
} 

Đối với những người không quen thuộc với các tính năng tối nghĩa hơn Scala, đây là một giải thích ngắn gọn:

scala.collection.parallel.`package` 

truy cập đối tượng gói có biến mặc địnhTaskSupport (có vẻ giống như biến tĩnh của Java, nhưng nó thực sự là biến thành viên của đối tượng gói). Các dấu gạch chéo là bắt buộc đối với mã định danh, vì package là từ khóa dành riêng. Sau đó, chúng ta lấy trường cuối cùng riêng mà chúng ta muốn (getField ("defaultTaskSupport") không hoạt động vì một số lý do? ...), yêu cầu nó có thể truy cập để có thể sửa đổi nó, và sau đó thay thế giá trị của nó bằng cách ForkJoinTaskSupport của chúng tôi.

Tôi chưa hiểu cơ chế chính xác của việc tạo các bộ sưu tập song song, nhưng mã nguồn của đặc tính Combiner cho thấy giá trị của defaultTaskSupport nên thấm qua các bộ sưu tập song song bằng cách nào đó.

Lưu ý rằng câu hỏi có chất lượng giống như câu hỏi cũ hơn: "Tôi có Math.random() trên mã nguồn của mình, làm cách nào để đặt hạt giống thành số cố định cho mục đích gỡ lỗi?" (Xem ví dụ: Set seed on Math.random()). Trong cả hai trường hợp, chúng ta có một loại biến "tĩnh" toàn cục mà chúng ta ngầm sử dụng ở một triệu địa điểm khác nhau, chúng ta muốn thay đổi nó, nhưng không có setters cho biến này => chúng ta sử dụng reflection.

Xấu xí như địa ngục, nhưng dường như chỉ hoạt động tốt. Nếu bạn cần giới hạn tổng số chủ đề, đừng quên rằng bộ thu gom rác chạy trên luồng riêng biệt.

+0

Bạn đẹp! Đã tìm kiếm một cách để làm chính xác điều đó. Đã hy vọng nó sẽ không được như vậy xấu xí, nhưng đó là hầu như không lỗi của bạn. Giao diện kỳ ​​quái vô ích là để đổ lỗi. – itsbruce

Các vấn đề liên quan