2013-08-05 59 views
5

Tôi được thông báo rằng tôi có thể sử dụng Grand Central Dispatch để chạy đồng thời n quy trình, theo cách không đồng bộ. Tài liệu nói rằng nếu các tiến trình nằm trong vòng lặp for, tôi có thể sử dụng hàm dispatch_apply. Nhưng bây giờ nó nói rằngGửi dispatch_apply đồng bộ hoặc không đồng bộ?

Lưu ý rằng dispatch_apply là đồng bộ, do đó, tất cả các khối được áp dụng sẽ hoàn thành vào thời điểm trả về.

Điều này có nghĩa là các khối được gửi đến hàng đợi bằng dispatch_apply được thực thi theo thứ tự? Nếu vậy, điểm của việc sử dụng đồng thời là gì? Sẽ không chậm lại là như nhau?

Trả lời

13

dispatch_apply, như đã nêu trong tài liệu, đồng bộ. Nó chạy một khối trên hàng đợi được chỉ định song song (nếu có thể) và chờ cho đến khi tất cả các khối trả về. Nếu bạn muốn chạy một khối chỉ một lần không đồng bộ, sử dụng dispatch_async, nếu bạn muốn chạy một khối nhiều lần song song mà không ngăn chặn hàng đợi hiện tại của bạn, chỉ cần gọi dispatch_apply trong dispatch_async:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 
    dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(size_t size) { 
     NSLog(@"%lu", size); 
    }); 
}); 
+0

Awesome, đó chính xác là những gì tôi muốn làm. Cảm ơn. – Jessica

6

Mục đích của đồng bộdispatch_applykhông đồng bộ gửi các giao diện vòng lặp bên trong tới các tài nguyên xử lý song song có sẵn. Do đó, hiệu suất vòng lặp tổng thể có thể tăng tốc.

Hiệu suất vòng lặp nhanh hơn? Rất có thể, Vâng. (xem caveat)

Chặn chuỗi gọi dispatch_apply? Có, giống như các khối vòng lặp cho đến khi hoàn thành.

Đối với GCD, dispatch_applyđồng bộ từ dispatch_apply sẽ không trở lại cho đến khi tất cả các không đồng bộ, song song nhiệm vụ mà dispatch_apply tạo đã hoàn thành.

Tuy nhiên, mỗi công việc cá nhân enqueued bởi dispatch_apply thể chạy như đồng thời không đồng bộ nhiệm vụ nếu mục tiêu queuekhông đồng bộ.

Ví dụ trong Swift:

let batchCount: Int = 10 
let queue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) 
dispatch_apply(batchCount, queue) { 
    (i: Int) -> Void in 
    print(i, terminator: " ") 
} 
print("\ndispatch_apply QOS_CLASS_UTILITY queue completed") 

mang lại sản lượng không có thứ tự như sau:

0 8 1 9 2 3 4 5 6 7 
dispatch_apply QOS_CLASS_UTILITY queue completed 

Vì vậy, dispatch_apply đồng bộ khối khi gọi, nhưng "hàng loạt" nhiệm vụ tạo ra bởi dispatch_apply có thể chạy đồng thời, không đồng bộ, song song với nhau.

Lưu ý rằng ...

công việc thực hiện trong mỗi lần lặp là khác biệt từ công việc thực hiện trong tất cả các lần lặp khác, và thứ tự mà mỗi vòng lặp liên tiếp hoàn thành là không quan trọng

Ngoài ra, lưu ý rằng sử dụng một hàng đợi nối tiếp cho các nhiệm vụ vòng lặp bên trong sẽ không có bất kỳ lợi ích hiệu suất nào.

Mặc dù sử dụng một hàng đợi nối tiếp được phép và làm điều đúng đắn cho mã của bạn, sử dụng một hàng đợi như vậy đã không có ưu điểm hiệu suất thực trên rời khỏi vòng lặp tại chỗ.

0

Bạn có thể lấy tốc độ hiệu suất lên bằng cách sử dụng gcl_create_dispatch_queue() với dispatch_apply()

Ví dụ:

@import Foundation; 
@import OpenCL;  // gcl_create_dispatch_queue() 

int main() { 
     dispatch_queue_t queue = gcl_create_dispatch_queue(CL_DEVICE_TYPE_ALL, NULL); 
     dispatch_apply(10, queue, ^(size_t t) { 
      // some code here 
     }); 
} 

Thông tin thêm: OpenCL Programming Guide for Mac

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