2010-10-18 27 views
16

Tôi hy vọng đây không phải là lạm dụng stackoverflow; gần đây tôi đã nhìn thấy một số câu hỏi tuyệt vời ở đây trên phần mở rộng song song, và nó đã được quan tâm của tôi piqued.Bạn có đang sử dụng Tiện ích mở rộng song song không?

Câu hỏi của tôi: Bạn có đang sử dụng Tiện ích mở rộng song song không và nếu có thì làm cách nào?

Tên tôi là Stephen Toub và tôi thuộc nhóm Nền tảng máy tính song song tại Microsoft. Chúng tôi là nhóm chịu trách nhiệm về Tiện ích mở rộng song song. Tôi luôn quan tâm đến việc nghe về cách các nhà phát triển đang sử dụng Tiện ích mở rộng song song (ví dụ: Parallel.For, PLINQ, ConcurrentDictionary, v.v.), trải nghiệm tích cực bạn đã có, trải nghiệm tiêu cực bạn đã có, yêu cầu tính năng cho tương lai và trên.
Nếu bạn sẵn sàng chia sẻ thông tin như vậy, vui lòng trả lời câu hỏi này hoặc cho tôi một cách riêng tư qua email theo số stoub at microsoft dot com.

Tôi rất mong được nghe từ bạn.

Cảm ơn trước!

+2

Vì câu hỏi này không thể có một câu trả lời đúng, tôi e rằng nó không thích hợp cho StackOverflow. Vì bạn đang ở trong nhóm MS, tôi sẽ không bỏ phiếu để đóng, nhưng có lẽ sẽ khác. Bạn có thể có may mắn hơn trên programmers.stackexchange.com và meta.stackoverflow.com. Ngoài ra, bạn có thể đánh dấu câu hỏi là "Wiki cộng đồng" để phiếu bầu không được tính vào/chống lại đại diện và ít có khả năng đóng cửa hơn. –

+0

Ok. Cảm ơn, Sam. Xin lỗi vì lạm dụng trang web. -Bước –

+2

@Stephen Toub, 12 giờ và 0 phiếu để đóng. Có vẻ như mọi người không quan tâm đến nó. Không có câu trả lời dù. –

Trả lời

0

Tôi đã sử dụng nó trên dự án của tôi MetaSharp. Tôi có một đường dẫn biên dịch dựa trên MSBuild cho DSL và một loại giai đoạn là giai đoạn Nhiều đến Nhiều. Giai đoạn M: M sử dụng .AsParallel.ForAll (...).

Đây là snippet:

protected sealed override IEnumerable<IContext> Process() 
{ 
    if (this.Input.Count() > 1) 
    { 
     this.Input 
      .AsParallel<IContext>() 
      .ForAll(this.Process); 
    } 
    else if (this.Input.Any()) 
    { 
     this.Process(this.Input.Single()); 
    } 

    return this.Input.ToArray(); 
} 
+4

Tôi muốn khuyên bạn nên 'this.Input.Skip (1). Bất kỳ()', để bạn có thể ngừng đếm sau khi nhấn đầu vào thứ hai . – StriplingWarrior

+1

Ý nghĩa: thay thế this.Input.Count()> 1 với this.Input.Skip (1) .Any(). – dthorpe

+0

Cuộc gọi tốt! Điều đó rất hữu ích. –

4

Tôi đang sử dụng TPL để làm lồng Parallel.ForEach cuộc gọi. Bởi vì tôi truy cập từ điển từ những cuộc gọi này, tôi phải sử dụng ConcurrentDictionary. Mặc dù nó rất hay, tôi có một vài vấn đề:

  • Các đại biểu bên trong ForEach không làm nhiều việc vì vậy tôi không nhận được nhiều song song. Hệ thống dường như dành phần lớn thời gian của nó tham gia chủ đề. Nó sẽ là tốt đẹp nếu có một cách để tìm ra lý do tại sao nó không nhận được đồng thời tốt hơn và cải thiện nó.

  • Lặp lại bên trong ForEach lặp lại trên ConcurrentDictionary trường hợp, điều này sẽ khiến hệ thống mất nhiều thời gian điều tra cho từ điển nếu tôi không thêm bộ đệm liệt kê.

  • Nhiều trường hợp ConcurrentDictionary của tôi thực sự được đặt, nhưng không có ConcurrentSet vì vậy tôi phải triển khai riêng của mình bằng ConcurrentDictionary.

  • ConcurrentDictionary không hỗ trợ cú pháp khởi tạo đối tượng vì vậy tôi không thể nói var dict = new ConcurrentDictionary<char, int> { { 'A', 65 } }; cũng có nghĩa là tôi không thể chỉ định ConcurrentDictionary chữ cho các thành viên của lớp học.

  • Có một số nơi tôi phải tra cứu khóa trong một số ConcurrentDictionary và gọi hàm đắt tiền để tạo ra giá trị nếu nó không tồn tại. Sẽ rất tuyệt nếu có quá tải GetOrAdd mất addValueFactory để giá trị chỉ có thể được tính nếu khóa không tồn tại. Điều này có thể được mô phỏng với .AddOrUpdate(key, addValueFactory, (k, v) => v) nhưng điều đó bổ sung thêm chi phí của cuộc gọi đại biểu bổ sung cho mọi lần tra cứu.

+0

Tôi nghĩ rằng bạn có thể tốt hơn mà không cần sử dụng làm tổ. Không có lý do gì để tạo ra nhiều nhiệm vụ hơn là có CPU - ít nhất là không nhiều hơn nữa. Tôi khuyên bạn nên loại bỏ Parallel.ForEach innter. –

+0

Joe H: Những cái bên trong thực sự làm cho quá trình này nhanh hơn 5-10%. – Gabe

1

Tôi chưa sử dụng rộng rãi, nhưng chắc chắn tôi đã sử dụng nó và tìm kiếm cơ hội trong cơ sở mã của chúng tôi để sử dụng nó (không may, chúng tôi là .NET-2.0 ràng buộc vào nhiều dự án của chúng tôi vẫn còn trong thời gian này).Một viên đá quý nhỏ tôi đến với bản thân mình là một bộ đếm từ duy nhất. Tôi nghĩ rằng đây là việc thực hiện nhanh nhất và chính xác nhất mà tôi có thể đưa ra - nếu ai đó có thể làm cho nó tốt hơn, đó sẽ là khiếp sợ:

private static readonly char[] delimiters = { ' ', '.', ',', ';', '\'', '-', ':', '!', '?', '(', ')', '<', '>', '=', '*', '/', '[', ']', '{', '}', '\\', '"', '\r', '\n' }; 
private static readonly Func<string, string> theWord = Word; 
private static readonly Func<IGrouping<string, string>, KeyValuePair<string, int>> theNewWordCount = NewWordCount; 
private static readonly Func<KeyValuePair<string, int>, int> theCount = Count; 

private static void Main(string[] args) 
{ 
    foreach (var wordCount in File.ReadAllText(args.Length > 0 ? args[0] : @"C:\DEV\CountUniqueWords\CountUniqueWords\Program.cs") 
     .Split(delimiters, StringSplitOptions.RemoveEmptyEntries) 
     .AsParallel() 
     .GroupBy(theWord, StringComparer.OrdinalIgnoreCase) 
     .Select(theNewWordCount) 
     .OrderByDescending(theCount)) 
    { 
     Console.WriteLine(
      "Word: \"" 
      + wordCount.Key 
      + "\" Count: " 
      + wordCount.Value); 
    } 

    Console.ReadLine(); 
} 

private static string Word(string word) 
{ 
    return word; 
} 

private static KeyValuePair<string, int> NewWordCount(IGrouping<string, string> wordCount) 
{ 
    return new KeyValuePair<string, int>(
     wordCount.Key, 
     wordCount.Count()); 
} 

private static int Count(KeyValuePair<string, int> wordCount) 
{ 
    return wordCount.Value; 
} 
+1

lol, bạn có cảm thấy khó chịu với các biểu thức lambda không? ;) Dù sao, tôi đã thử mã này với sách điện tử "Chúa tể của những chiếc nhẫn" làm đầu vào. Nó cung cấp cho các kết quả tương tự có hoặc không có AsParallel, vì vậy tôi đoán các phần mở rộng song song không thực sự giúp ích trong trường hợp đó ...Tôi cũng đã viết một bản thực thi ngắn hơn (dọc theo cùng một dòng) nhanh gấp hai lần, vì vậy việc triển khai của bạn có lẽ không phải là "triển khai nhanh nhất và ngắn gọn nhất có thể đưa ra";). Tuy nhiên, đó là một bài tập thú vị ... –

+1

Vâng, chúng ta hãy xem nó, người đàn ông! –

+0

@Thomas - Có thể bạn không nhận được thông báo cho nhận xét của Jesse. Hãy để nhận xét này đóng vai trò là thông báo đó. – Greg

0

Chúng tôi không sử dụng nó rộng rãi, nhưng nó đã chắc chắn đi thuận tiện.

tôi đã có thể làm giảm thời gian chạy của một vài trong số các bài kiểm tra đơn vị còn chạy của chúng tôi để khoảng 1/3 thời gian ban đầu của họ chỉ bằng cách gói một số bước thời gian chuyên sâu hơn trong một cuộc gọi Parallel.Invoke().

Tôi cũng thích sử dụng thư viện song song để thử nghiệm an toàn luồng. Tôi đã bắt gặp và báo cáo một vài vấn đề luồng với Ninject với mã một cái gì đó như thế này:

var repositoryTypes = from a in CoreAssemblies 
        from t in a.GetTypes() 
        where t.Name.EndsWith("Repository") 
        select t; 
repositoryTypes.ToList().AsParallel().ForAll(
    repositoryType => _kernel.Get(repositoryType)); 

Trong mã sản xuất thực tế của chúng tôi, chúng tôi sử dụng một số phần mở rộng song song để chạy một số hành động hội nhập mà có nghĩa vụ phải chạy mỗi vài phút và bao gồm chủ yếu là kéo dữ liệu từ các dịch vụ web. Điều này có lợi thế đặc biệt của tính song song vì độ trễ cao vốn có trong các kết nối web và cho phép công việc của chúng ta kết thúc chạy trước khi chúng được kích hoạt lại.

0

Tôi đang sử dụng ConcurrentDictionary lưu trữ 100 triệu mục +. Ứng dụng của tôi sử dụng khoảng 8 GB bộ nhớ tại thời điểm đó. ConcurrentDictionary sau đó quyết định nó muốn phát triển trên một Add khác. Và nó muốn phát triển một LOT rõ ràng (một số thuật toán prima nội bộ) khi nó hết bộ nhớ. Đây là trên x64 với 32GB bộ nhớ.

Vì vậy, tôi muốn một boolean chặn tự động tái sinh/từ bỏ lại từ điển (đồng thời). Sau đó tôi sẽ khởi tạo từ điển lúc tạo bằng một nhóm cố định các thùng (điều này không giống như một công suất cố định!). Và nó sẽ trở nên chậm hơn một chút theo thời gian vì ngày càng có nhiều vật phẩm trong một cái xô. Nhưng điều này sẽ ngăn chặn việc phục hồi và thoát khỏi bộ nhớ quá nhanh và không cần thiết.

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