Có những thực tiễn không dùng cho lập trình đa luồng và đa bộ xử lý mà tôi không còn nên sử dụng nữa?


36

Trong những ngày đầu của FORTRAN và BASIC, về cơ bản, tất cả các chương trình được viết bằng các câu lệnh GOTO. Kết quả là mã spaghetti và giải pháp được lập trình có cấu trúc.

Tương tự, con trỏ có thể khó kiểm soát các đặc điểm trong các chương trình của chúng tôi. C ++ bắt đầu với rất nhiều con trỏ, nhưng nên sử dụng các tài liệu tham khảo. Các thư viện như STL có thể giảm một số phụ thuộc của chúng tôi. Ngoài ra còn có các thành ngữ để tạo các con trỏ thông minh có các đặc tính tốt hơn và một số phiên bản của C ++ cho phép các tham chiếu và mã được quản lý.

Các thực hành lập trình như kế thừa và đa hình sử dụng rất nhiều con trỏ phía sau hậu trường (giống như, trong khi, lập trình có cấu trúc tạo mã chứa đầy các hướng dẫn chi nhánh). Các ngôn ngữ như Java loại bỏ các con trỏ và sử dụng bộ sưu tập rác để quản lý dữ liệu được phân bổ động thay vì phụ thuộc vào các lập trình viên để khớp với tất cả các câu lệnh mới và xóa của chúng.

Trong bài đọc của tôi, tôi đã thấy các ví dụ về lập trình đa tiến trình và đa luồng dường như không sử dụng các từ ngữ nghĩa. Họ có sử dụng cùng một thứ với các tên khác nhau hay họ có cách thức mới để cấu trúc bảo vệ tài nguyên khỏi việc sử dụng đồng thời?

Ví dụ, một ví dụ cụ thể về một hệ thống để lập trình đa luồng với bộ xử lý đa lõi là OpenMP. Nó đại diện cho một khu vực quan trọng như sau, mà không sử dụng semaphores, dường như không được bao gồm trong môi trường.

th_id = omp_get_thread_num();
#pragma omp critical
{
  cout << "Hello World from thread " << th_id << '\n';
}

Ví dụ này là một đoạn trích từ: http://en.wikipedia.org/wiki/OpenMP

Ngoài ra, sự bảo vệ tương tự của các luồng với nhau bằng cách sử dụng semaphores với các hàm Wait () và signal () có thể trông như thế này:

wait(sem);
th_id = get_thread_num();
cout << "Hello World from thread " << th_id << '\n';
signal(sem);

Trong ví dụ này, mọi thứ khá đơn giản và chỉ cần một đánh giá đơn giản là đủ để hiển thị các cuộc gọi chờ () và tín hiệu () được khớp và thậm chí với rất nhiều sự đồng thời, an toàn luồng được cung cấp. Nhưng các thuật toán khác phức tạp hơn và sử dụng nhiều semaphores (cả nhị phân và đếm) trải rộng trên nhiều hàm với các điều kiện phức tạp có thể được gọi bởi nhiều luồng. Hậu quả của việc tạo ra bế tắc hoặc không làm cho mọi thứ trở nên an toàn có thể khó quản lý.

Các hệ thống như OpenMP có loại bỏ các vấn đề với semaphores không?
Họ có di chuyển vấn đề ở nơi khác không?
Làm cách nào để chuyển đổi semaphore yêu thích của tôi bằng thuật toán để không sử dụng semaphores nữa?


Chinh xac thi bạn đang noi cai gi vậy? Bạn đã thấy gì?
Svick

4
Không có nghĩa là thô lỗ, nhưng bạn có thể đã loại bỏ ba đoạn đầu tiên. Họ không thực sự chịu đựng câu hỏi của bạn, và họ quá hiểu về kết luận của họ và sẽ tạo ra rất nhiều tranh luận.
dbracey

1
Whoa, chỉnh sửa lớn. Tôi đã đâm một câu trả lời. Câu hỏi vẫn là những người lang thang xung quanh thông qua GOTO, con trỏ, tính kế thừa và tính đa hình, nhưng trong câu trả lời của tôi, tôi đã đặt những vấn đề này sang một bên và tập trung vào câu hỏi "thực tiễn không dùng nữa".
Stuart Marks

Câu trả lời:


15

Có các kỹ thuật và thực hành lập trình đồng thời mà người ta không nên sử dụng nữa không? Tôi muốn nói .

Một kỹ thuật lập trình đồng thời sớm mà dường như hiếm ngày nay là lập trình điều khiển ngắt . Đây là cách UNIX hoạt động trong những năm 1970. Xem Bình luận của Lions về Thiết kế của UNIX hoặc Bach của Hệ điều hành UNIX . Tóm lại, kỹ thuật này là tạm dừng các ngắt tạm thời trong khi thao tác cấu trúc dữ liệu và sau đó khôi phục các ngắt sau đó. Các BSD SPL (9) người đàn ông trangcó một ví dụ về phong cách mã hóa này. Lưu ý rằng các ngắt được định hướng theo phần cứng và mã thể hiện mối quan hệ ngầm giữa loại ngắt phần cứng và các cấu trúc dữ liệu được liên kết với phần cứng đó. Ví dụ, mã thao tác bộ đệm I / O đĩa cần tạm dừng các ngắt từ phần cứng bộ điều khiển đĩa trong khi làm việc với các bộ đệm đó.

Phong cách lập trình này được sử dụng bởi các hệ điều hành trên phần cứng không xử lý. Nó hiếm hơn nhiều cho các ứng dụng để đối phó với các ngắt. Một số hệ điều hành bị gián đoạn phần mềm và tôi nghĩ mọi người đã cố gắng xây dựng các hệ thống luồng hoặc coroutine trên đầu chúng, nhưng điều này không phổ biến lắm. (Chắc chắn không có trong thế giới UNIX.) Tôi nghi ngờ rằng lập trình kiểu gián đoạn ngày nay bị giới hạn trong các hệ thống nhúng nhỏ hoặc hệ thống thời gian thực.

Semaphores là một sự tiến bộ vượt trội vì chúng là các cấu trúc phần mềm (không liên quan đến phần cứng), chúng cung cấp sự trừu tượng hóa trên các cơ sở phần cứng và chúng cho phép đa luồng và đa xử lý. Vấn đề chính là chúng không có cấu trúc. Lập trình viên chịu trách nhiệm duy trì mối quan hệ giữa mỗi semaphore và các cấu trúc dữ liệu mà nó bảo vệ, trên toàn cầu trong toàn bộ chương trình. Vì lý do này, tôi nghĩ rằng semaphores trần hiếm khi được sử dụng ngày nay.

Một bước tiến nhỏ khác là một màn hình , đóng gói các cơ chế kiểm soát đồng thời (khóa và điều kiện) với dữ liệu được bảo vệ. Điều này đã được chuyển sang hệ thống Mesa (liên kết thay thế) và từ đó vào Java. (Nếu bạn đọc bài viết về Mesa này, bạn có thể thấy rằng các khóa và điều kiện của màn hình Java được sao chép gần như nguyên văn từ Mesa.) trong màn hình.

Có các cấu trúc thư viện bổ sung, chẳng hạn như các java.util.concurrentcấu trúc trong gói của Java , bao gồm nhiều cấu trúc dữ liệu đồng thời cao và các cấu trúc nhóm luồng. Chúng có thể được kết hợp với các kỹ thuật bổ sung như giam cầm luồng và tính bất biến hiệu quả. Xem Java đồng thời trong thực tế của Goetz et. al. để thảo luận thêm. Thật không may, nhiều lập trình viên vẫn đang cuộn các cấu trúc dữ liệu của riêng họ với các khóa và điều kiện, khi họ thực sự chỉ nên sử dụng một cái gì đó giống như ConcảnHashMap , nơi các tác giả thư viện đã thực hiện việc nâng vật nặng.

Tất cả mọi thứ ở trên đều có chung một số đặc điểm quan trọng: chúng có nhiều luồng kiểm soát tương tác qua trạng thái có thể thay đổi được chia sẻ trên toàn cầu . Vấn đề là lập trình theo phong cách này vẫn dễ bị lỗi. Thật dễ dàng để một lỗi nhỏ không được chú ý, dẫn đến hành vi sai trái khó tái tạo và chẩn đoán. Có thể không có lập trình viên nào "đủ cẩn thận và siêng năng" để phát triển các hệ thống lớn theo cách này. Ít nhất, rất ít. Vì vậy, tôi muốn nói rằng nên tránh lập trình đa luồng với trạng thái chia sẻ, có thể thay đổi nếu có thể.

Thật không may, nó không hoàn toàn rõ ràng liệu nó có thể tránh được trong mọi trường hợp. Rất nhiều chương trình vẫn được thực hiện theo cách này. Sẽ thật tốt khi thấy điều này được thay thế bởi một cái gì đó khác. Câu trả lời từ Jarrod Robersondavidk01 chỉ ra các kỹ thuật như dữ liệu bất biến, lập trình chức năng, STM và truyền tin nhắn. Có nhiều điều để giới thiệu họ, và tất cả đang được tích cực phát triển. Nhưng tôi không nghĩ rằng họ đã thay thế hoàn toàn trạng thái biến đổi được chia sẻ kiểu cũ tốt.

EDIT: đây là câu trả lời của tôi cho các câu hỏi cụ thể ở cuối.

Tôi không biết nhiều về OpenMP. Ấn tượng của tôi là nó có thể rất hiệu quả đối với các vấn đề song song cao như mô phỏng số. Nhưng nó không có vẻ mục đích chung. Các cấu trúc semaphore có vẻ khá thấp và yêu cầu lập trình viên duy trì mối quan hệ giữa semaphores và cấu trúc dữ liệu được chia sẻ, với tất cả các vấn đề tôi đã mô tả ở trên.

Nếu bạn có một thuật toán song song sử dụng semaphores, tôi không biết bất kỳ kỹ thuật chung nào để biến đổi nó. Bạn có thể tái cấu trúc nó thành các đối tượng và sau đó xây dựng một số trừu tượng xung quanh nó. Nhưng nếu bạn muốn sử dụng một cái gì đó như truyền tin nhắn, tôi nghĩ bạn thực sự cần phải đánh giá lại toàn bộ vấn đề.


Cảm ơn, đây là thông tin tuyệt vời. Tôi sẽ xem qua các tài liệu tham khảo và tìm hiểu sâu hơn về các khái niệm mà bạn đề cập mới đối với tôi.
Nhà phát triển

+1 cho java.util.conc hiện và đồng ý với nhận xét - đó là trong JDK kể từ 1.5 và tôi hiếm khi thấy nó được sử dụng.
MebAlone

1
Tôi muốn bạn nhấn mạnh tầm quan trọng của việc không cuộn các cấu trúc của riêng bạn khi các cấu trúc đã tồn tại. Rất nhiều, rất nhiều lỗi ...
corsiKa

Tôi không nghĩ chính xác khi nói, "Semaphores là một bước tiến vượt trội vì chúng là các cấu trúc phần mềm (không liên quan đến phần cứng) ". Semaphores phụ thuộc vào CPU để thực hiện lệnh So sánh và Hoán đổi , hoặc đó là các biến thể đa lõi .
Josh Pearce

@JoshPearce Tất nhiên các semaphores được triển khai bằng các cấu trúc phần cứng, nhưng chúng là một sự trừu tượng độc lập với bất kỳ cấu trúc phần cứng cụ thể nào, chẳng hạn như CAS, test-and-set, cmpxchng, v.v.
Stuart Marks

28

Trả lời câu hỏi

Sự đồng thuận chung được chia sẻ trạng thái có thể thay đổi là Bad ™ và trạng thái bất biến là Good ™, được chứng minh là chính xác và đúng và lặp đi lặp lại bởi các ngôn ngữ chức năng và ngôn ngữ mệnh lệnh.

Vấn đề là các ngôn ngữ mệnh lệnh chính thống không được thiết kế để xử lý cách làm việc này, mọi thứ sẽ không thay đổi đối với các ngôn ngữ đó qua đêm. Đây là nơi so sánh GOTOlà thiếu sót. Trạng thái bất biến và thông điệp truyền qua là một giải pháp tuyệt vời nhưng nó cũng không phải là thuốc chữa bách bệnh.

Tiền đề thiếu sót

Câu hỏi này dựa trên sự so sánh với một tiền đề thiếu sót; đó GOTOlà vấn đề thực tế và đã bị Hội đồng các nhà thiết kế ngôn ngữ và công nghệ phần mềm Intergalatic phổ biến một cách nào đó ! Nếu không có GOTOcơ chế thì ASM sẽ không hoạt động. Tương tự với tiền đề rằng con trỏ thô là vấn đề với C hoặc C ++ và một số cách con trỏ thông minh là thuốc chữa bách bệnh, chúng không.

GOTOkhông phải là vấn đề, lập trình viên là vấn đề. Cùng đi cho trạng thái đột biến được chia sẻ . Nó không phải là vấn đề , chính các lập trình viên sử dụng nó mới là vấn đề. Nếu có một cách để tạo mã sử dụng trạng thái có thể thay đổi được chia sẻ theo cách không bao giờ có bất kỳ điều kiện chủng tộc hoặc lỗi nào, thì đó không phải là vấn đề. Giống như nếu bạn không bao giờ viết mã spaghetti với GOTOhoặc các cấu trúc tương đương thì đó cũng không phải là vấn đề.

Giáo dục là thần dược

Các lập trình viên ngốc là những gì deprecated, mọi ngôn ngữ phổ biến vẫn có GOTOcấu trúc trực tiếp hoặc gián tiếp và đó là best practicekhi được sử dụng đúng cách trong mọi ngôn ngữ có loại cấu trúc này.

VÍ DỤ: Java có các nhãntry/catch/finallycả hai đều trực tiếp hoạt động như các GOTOcâu lệnh.

Hầu hết các lập trình viên Java mà tôi nói chuyện thậm chí không biết những gì immutablethực sự có nghĩa là bên ngoài họ lặp lại the String class is immutablevới một thây ma như trong mắt họ. Họ chắc chắn không biết cách sử dụng finaltừ khóa đúng cách để tạo một immutablelớp. Vì vậy, tôi khá chắc chắn rằng họ không biết tại sao việc nhắn tin chuyển qua sử dụng tin nhắn bất biến lại tuyệt vời đến vậy và tại sao trạng thái biến đổi được chia sẻ lại không tuyệt vời như vậy.


3
+1 Câu trả lời tuyệt vời, được viết rõ ràng và xác định mô hình cơ bản của trạng thái có thể thay đổi. IUBLDSEU sẽ trở thành một meme :)
Dibbeke

2
GOTO là một từ mã cho 'làm ơn, không thực sự vui lòng bắt đầu một cuộc chiến nảy lửa ở đây, tôi nhân đôi con chó dám làm bạn'. Câu hỏi này dập tắt ngọn lửa nhưng không thực sự đưa ra một câu trả lời hay. Những đề cập đáng trân trọng về lập trình chức năng và tính bất biến là tuyệt vời nhưng không có thịt cho những tuyên bố đó.
Evan Plaice

1
Đây dường như là một câu trả lời mâu thuẫn. Đầu tiên, bạn nói "A là xấu, B là tốt", sau đó bạn nói "Những kẻ ngốc đã bị phản đối". Không phải điều tương tự áp dụng cho đoạn đầu tiên? Tôi không thể lấy phần cuối câu trả lời của bạn và nói "Trạng thái có thể thay đổi được chia sẻ là cách thực hành tốt nhất khi được sử dụng đúng cách trong mọi ngôn ngữ". Ngoài ra, "bằng chứng" là một từ rất mạnh. Bạn không nên sử dụng nó trừ khi bạn có bằng chứng thực sự mạnh mẽ.
luiscubal

2
Đó không phải là ý định của tôi để bắt đầu một cuộc chiến lửa. Cho đến khi Jarrod phản ứng với bình luận của tôi, đã nghĩ rằng GOTO không gây tranh cãi và sẽ hoạt động tốt trong một sự tương tự. Khi tôi viết câu hỏi, điều đó không xảy ra với tôi, nhưng Dijkstra hoàn toàn không có mặt trên cả GOTO và semaphores. Edsger Dijkstra có vẻ như là một người khổng lồ đối với tôi, và được ghi nhận với việc phát minh ra semaphores (1965) và đầu (năm 1968) nghiên cứu về GOTOs. Phương pháp vận động của Dijkstra thường rất tàn nhẫn và đối đầu. Tranh cãi / đối đầu có hiệu quả với anh ta, nhưng tôi chỉ muốn ý tưởng về những sự thay thế có thể cho semaphores.
DeveloperDon

1
Nhiều chương trình được cho là mô hình hóa những thứ mà trong thế giới thực là có thể thay đổi. Nếu vào lúc 5:37 sáng, vật thể số 451 giữ trạng thái của một thứ gì đó trong thế giới thực tại thời điểm đó (5:37 sáng) và trạng thái của vật thể trong thế giới thực sau đó thay đổi, thì có thể nhận dạng của vật thể đại diện trạng thái của vật trong thế giới thực là bất biến (tức là vật sẽ luôn được đại diện bởi đối tượng # 451) hoặc cho đối tượng # 451 là bất biến, nhưng không phải cả hai. Trong nhiều trường hợp, việc có danh tính là bất biến sẽ hữu ích hơn so với việc đối tượng # 451 là bất biến.
supercat

27

Cơn thịnh nộ mới nhất trong giới học thuật dường như là Bộ nhớ giao dịch phần mềm (STM) và nó hứa hẹn sẽ lấy tất cả các chi tiết đầy lông của lập trình đa luồng ra khỏi tay các lập trình viên bằng cách sử dụng công nghệ biên dịch đủ thông minh. Đằng sau hậu trường, nó vẫn là ổ khóa và ngữ nghĩa nhưng bạn là lập trình viên không phải lo lắng về điều đó. Lợi ích của phương pháp đó vẫn chưa rõ ràng và không có đối thủ rõ ràng.

Erlang sử dụng chuyển tin nhắn và các tác nhân để đồng thời và đó là một mô hình đơn giản hơn để làm việc với STM. Với thông điệp truyền qua, bạn hoàn toàn không có khóa và semaphores để lo lắng vì mỗi tác nhân hoạt động trong vũ trụ mini của riêng mình nên không có điều kiện cuộc đua liên quan đến dữ liệu. Bạn vẫn có một số trường hợp cạnh kỳ lạ nhưng chúng không phức tạp như sống động và bế tắc. Các ngôn ngữ JVM có thể sử dụng Akka và nhận được tất cả các lợi ích của việc truyền thông điệp và các tác nhân nhưng không giống như Erlang, JVM không hỗ trợ tích hợp cho các diễn viên nên cuối ngày Akka vẫn sử dụng các luồng và khóa nhưng bạn là lập trình viên không phải lo lắng về nó.

Mô hình khác tôi biết rằng không sử dụng khóa và luồng là bằng cách sử dụng tương lai mà thực sự chỉ là một hình thức lập trình không đồng bộ khác.

Tôi không chắc có bao nhiêu công nghệ này có sẵn trong C ++ nhưng rất có thể nếu bạn đang nhìn thấy thứ gì đó không rõ ràng bằng cách sử dụng các luồng và khóa thì đó sẽ là một trong những kỹ thuật trên để quản lý đồng thời.


+1 cho thuật ngữ mới "chi tiết lông". Người đàn ông LOL. Tôi không thể ngừng cười với thuật ngữ mới này. Tôi đoán từ giờ tôi sẽ sử dụng "mã lông".
Saeed Neamati

1
@Saeed: Tôi đã nghe thấy biểu hiện đó trước đây, nó không phải là hiếm. Tôi đồng ý rằng thật buồn cười :-)
Cameron

1
Câu trả lời tốt. .NET CLI được cho là cũng có hỗ trợ cho tín hiệu (trái ngược với khóa) nhưng tôi vẫn chưa bắt gặp một ví dụ trong đó nó thay thế hoàn toàn việc khóa. Tôi không chắc nếu async được tính. Nếu bạn đang nói về các nền tảng như Javascript / NodeJ, thì chúng thực sự là một luồng và chỉ tốt hơn khi tải IO cao vì chúng ít bị giới hạn tài nguyên hơn nhiều (ví dụ như trên một tấn bối cảnh vứt bỏ). Trên các tải nặng của CPU, có rất ít / không có lợi ích gì khi sử dụng lập trình async.
Evan Plaice

1
Câu trả lời thú vị, tôi đã không bắt gặp tương lai trước đây. Cũng lưu ý rằng bạn vẫn có thể có bế tắclivelock trong các hệ thống chuyển tin nhắn như Erlang . CSP cho phép bạn chính thức lý do về bế tắclivelock nhưng bản thân nó không ngăn chặn được.
Đánh dấu gian hàng

1
Tôi sẽ thêm Khóa miễn phí và chờ cấu trúc dữ liệu miễn phí vào danh sách đó.
ném đá

3

Tôi nghĩ rằng điều này chủ yếu là về mức độ trừu tượng. Rất thường xuyên trong lập trình, rất hữu ích để trừu tượng hóa một số chi tiết theo cách an toàn hơn hoặc dễ đọc hơn hoặc một cái gì đó tương tự.

Điều này áp dụng cho các cấu trúc điều khiển: ifs, fors và chẵn try- catchcác khối chỉ là trừu tượng hóa trên gotos. Các tóm tắt này hầu như luôn hữu ích, bởi vì chúng làm cho mã của bạn dễ đọc hơn. Nhưng có những trường hợp khi bạn vẫn sẽ cần sử dụng goto(ví dụ: nếu bạn đang viết lắp ráp bằng tay).

Điều này cũng áp dụng cho quản lý bộ nhớ: Con trỏ thông minh C ++ và GC là trừu tượng hóa so với con trỏ thô và phân bổ bộ nhớ thủ công. Và đôi khi, những trừu tượng này không phù hợp, ví dụ khi bạn thực sự cần hiệu suất tối đa.

Và điều tương tự cũng áp dụng cho đa luồng: những thứ như tương lai và diễn viên chỉ là trừu tượng hóa trên các chủ đề, ngữ nghĩa, mutexes và hướng dẫn CAS. Các tóm tắt như vậy có thể giúp bạn làm cho mã của bạn dễ đọc hơn nhiều và chúng cũng giúp bạn tránh các lỗi. Nhưng đôi khi, chúng chỉ đơn giản là không thích hợp.

Bạn nên biết những công cụ bạn có sẵn và những lợi thế và bất lợi của chúng là gì. Sau đó, bạn có thể chọn sự trừu tượng chính xác cho nhiệm vụ của mình (nếu có). Mức độ trừu tượng cao hơn không làm giảm mức độ thấp hơn, sẽ luôn có một số trường hợp sự trừu tượng hóa không phù hợp và lựa chọn tốt nhất là sử dụng cách thức cũ của Drake.


Cảm ơn, bạn đang nắm bắt được sự tương tự và tôi không có ý tưởng định sẵn hoặc thậm chí là rìu để xem liệu câu trả lời của WRT có phải là chúng không hoặc không được phản đối. Các câu hỏi lớn hơn đối với tôi là có những cách tốt hơn và trong các hệ thống dường như không có ngữ nghĩa thiếu một cái gì đó quan trọng và chúng sẽ không thể thực hiện đầy đủ các thuật toán đa luồng.
Nhà phát triển

2

Có, nhưng bạn không có khả năng gặp phải một số trong số họ.

Vào thời xưa, người ta thường sử dụng các phương pháp chặn (đồng bộ hóa rào cản) bởi vì viết các đột biến tốt rất khó để thực hiện đúng. Bạn vẫn có thể thấy dấu vết của điều này trong những điều gần đây Việc sử dụng các thư viện đồng thời hiện đại mang đến cho bạn một bộ công cụ phong phú hơn và được kiểm tra kỹ lưỡng để song song hóa và phối hợp giữa các quá trình.

Tương tự như vậy, một thực tiễn cũ hơn là viết mã phức tạp để bạn có thể tìm ra cách song song hóa thủ công. Hình thức tối ưu hóa này (có khả năng gây hại, nếu bạn hiểu sai) phần lớn cũng đã xuất hiện ngoài cửa sổ với sự ra đời của trình biên dịch làm điều này cho bạn, tháo gỡ các vòng lặp nếu cần thiết, theo dự đoán theo các nhánh, v.v. Tuy nhiên, đây không phải là công nghệ mới , được ít nhất 15 năm trên thị trường. Lợi dụng những thứ như nhóm luồng cũng phá vỡ một số mã thực sự khó khăn của năm qua.

Vì vậy, có lẽ thực tế không dùng nữa là tự viết mã đồng thời, thay vì sử dụng các thư viện được kiểm tra tốt, hiện đại.


Cảm ơn. Có vẻ như có tiềm năng lớn để sử dụng lập trình đồng thời, nhưng nó có thể là hộp Pandora nếu không được sử dụng một cách có kỷ luật.
Nhà phát

2

Grand Central Dispatch của Apple là một bản tóm tắt thanh lịch đã thay đổi suy nghĩ của tôi về sự tương tranh. Sự tập trung của nó vào hàng đợi làm cho việc triển khai logic không đồng bộ trở thành một thứ tự đơn giản hơn, theo kinh nghiệm khiêm tốn của tôi.

Khi tôi lập trình trong các môi trường có sẵn, nó đã thay thế hầu hết các cách sử dụng luồng, khóa và liên lạc giữa các luồng của tôi.


1

Một trong những thay đổi lớn đối với lập trình song song là CPU nhanh hơn rất nhiều so với trước đây, nhưng để đạt được hiệu năng đó, cần có bộ đệm đầy độc đáo. Nếu bạn cố gắng chạy một số luồng cùng lúc liên tục hoán đổi giữa chúng, thì hầu như bạn sẽ luôn bị vô hiệu hóa bộ đệm cho mỗi luồng (tức là mỗi luồng yêu cầu dữ liệu khác nhau để hoạt động) và cuối cùng bạn sẽ giết hiệu năng nhiều hơn bạn Được sử dụng với CPU chậm hơn.

Đây là một lý do tại sao các khung công tác không đồng bộ hoặc dựa trên tác vụ (ví dụ: Grand Central Dispatch hoặc Intel's TBB) phổ biến hơn, chúng chạy mã 1 tác vụ một lúc, hoàn thành trước khi chuyển sang phần tiếp theo - tuy nhiên, bạn phải mã hóa từng phần mỗi tác vụ sẽ mất ít thời gian trừ khi bạn muốn vặn thiết kế (tức là các tác vụ song song của bạn thực sự được xếp hàng). Các tác vụ chuyên sâu của CPU được chuyển đến lõi CPU thay thế thay vì được xử lý trên một luồng xử lý tất cả các tác vụ. Nó cũng dễ quản lý hơn nếu không có quá trình xử lý đa luồng thực sự đang diễn ra.


Thật tuyệt, cảm ơn bạn đã tham khảo công nghệ của Apple và Intel. Là câu trả lời của bạn chỉ ra những thách thức của việc quản lý chủ đề đến mối quan hệ cốt lõi? Một số vấn đề về hiệu năng bộ đệm được giảm bớt vì bộ xử lý đa lõi có thể lặp lại bộ đệm L1 trên mỗi lõi? Ví dụ: software.intel.com/en-us/articles/ Khăn Bộ nhớ cache tốc độ cao cho bốn lõi với nhiều lần truy cập bộ đệm hơn có thể nhanh hơn gấp 4 lần so với một lõi có nhiều bộ nhớ cache hơn trên cùng một dữ liệu. Ma trận nhân có thể. Lập lịch ngẫu nhiên 32 luồng trên 4 lõi không thể. Hãy sử dụng mối quan hệ và nhận được 32 lõi.
DeveloperDon

không thực sự mặc dù cùng một vấn đề - mối quan hệ cốt lõi chỉ đề cập đến vấn đề mà một nhiệm vụ bị trả lại từ cốt lõi đến cốt lõi. Vấn đề tương tự của nó nếu một tác vụ bị gián đoạn, được thay thế bằng một nhiệm vụ mới, thì nhiệm vụ ban đầu tiếp tục trên cùng một lõi. Intel đang nói rằng: bộ nhớ cache = nhanh, bộ nhớ cache = chậm, bất kể số lượng lõi. Tôi nghĩ họ đang cố thuyết phục bạn mua chip của họ chứ không phải AMD :)
gbjbaanb
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.