Đa luồng quan trọng như thế nào trong ngành công nghiệp phần mềm hiện tại? [đóng cửa]


59

Tôi đã có gần 3 năm kinh nghiệm viết các ứng dụng web bằng Java bằng cách sử dụng các khung công tác MVC (như các thanh chống). Tôi chưa bao giờ viết mã đa luồng cho đến bây giờ mặc dù tôi đã viết mã cho các chuỗi bán lẻ lớn.

Tôi nhận được một vài câu hỏi về đa luồng trong các cuộc phỏng vấn và tôi thường trả lời chúng (chủ yếu là những câu hỏi đơn giản). Điều này khiến tôi tự hỏi rằng Multithreading quan trọng như thế nào trong kịch bản ngành hiện tại?


8
Bạn có thể không làm như vậy một cách rõ ràng nhưng bạn chắc chắn đã tận dụng lợi thế của nó đằng sau hậu trường.
Martin York

1
Tôi quá hiếm khi làm việc với mã đa luồng cho công việc, nhưng tôi cố gắng đọc nó / có thể thảo luận về nó trong một cuộc phỏng vấn. Tôi sẽ không muốn làm việc với các lập trình viên không nhận được các luồng và tôi không muốn làm việc với các lập trình viên, những người không quan tâm liệu các lập trình viên khác có nhận được các luồng hay không.
Công việc

1
Tôi hiếm khi sử dụng nó trong phát triển web, nhưng tôi nghĩ nó phổ biến hơn ở nơi khác. Chẳng hạn, gần đây tôi đã viết một ứng dụng Android và nhận ra rằng bạn bắt buộc phải sử dụng đa luồng nếu bạn có bất kỳ hoạt động mạng nào.
jwegner

4
Đó không phải là đa luồng, điều đó quan trọng, đó là tính toán song song. Nếu bạn nghĩ rằng tất cả mọi yêu cầu duy nhất đến ứng dụng web của bạn đều nằm trong chuỗi ... bạn phải hút một thứ gì đó.
user606723

1
Khả năng "Nghĩ bên ngoài luồng" rất tốt ngay cả đối với lập trình luồng đơn. Bạn mất rất nhiều tiền cho phép, và mã của bạn thường mạnh mẽ hơn và có thể tái sử dụng.
corsiKa

Câu trả lời:


92

Nó là vô cùng quan trọng.

Điều quan trọng hơn là hiểu rằng đa luồng chỉ là một cách để giải quyết vấn đề không đồng bộ. Môi trường kỹ thuật trong đó nhiều người hiện đang viết phần mềm khác với môi trường phát triển phần mềm lịch sử (của các ứng dụng nguyên khối thực hiện tính toán hàng loạt) theo hai cách chính:

  • Máy nhiều lõi hiện đang phổ biến. Chúng ta không còn có thể mong đợi tốc độ xung nhịp hoặc mật độ bóng bán dẫn tăng theo đơn đặt hàng cường độ. Giá của tính toán sẽ tiếp tục giảm, nhưng nó sẽ giảm vì rất nhiều sự song song. Chúng ta sẽ phải tìm cách tận dụng sức mạnh đó.

  • Máy tính hiện đang được kết nối nhiều và các ứng dụng hiện đại phụ thuộc vào việc có thể lấy thông tin phong phú từ nhiều nguồn khác nhau.

Từ quan điểm tính toán, hai yếu tố này về cơ bản tập trung vào cùng một ý tưởng cốt lõi: thông tin ngày càng có sẵn theo kiểu không đồng bộ . Cho dù thông tin bạn cần đang được tính toán trên một con chip khác trong máy của bạn hay trên một con chip cách nửa vòng trái đất không thực sự quan trọng. Dù bằng cách nào, bộ xử lý của bạn đang ngồi đó đốt cháy hàng tỷ chu kỳ một giây để chờ thông tin khi nó có thể thực hiện công việc hữu ích.

Vì vậy, những gì quan trọng bây giờ, và những gì sẽ còn quan trọng hơn trong tương lai, không phải là đa luồng mỗi se, mà là, xử lý sự không đồng bộ . Đa luồng chỉ là một cách để làm điều đó - một cách phức tạp, dễ bị lỗi sẽ chỉ trở nên phức tạp hơn và dễ bị lỗi hơn khi các chip mô hình bộ nhớ yếu được sử dụng rộng rãi hơn.

Thách thức đối với các nhà cung cấp công cụ là đưa ra một cách nào đó tốt hơn là đa luồng cho khách hàng của chúng tôi để đối phó với cơ sở hạ tầng không đồng bộ mà họ sẽ sử dụng trong tương lai.


5
+1 cho một câu trả lời xuất sắc, nó xứng đáng nhận được nhiều tín dụng hơn nỗ lực khiêm tốn của riêng tôi.
Péter Török

2
Thông tin ngày càng sẽ có sẵn trong một cách không đồng bộ. Nếu đó không phải là sự thật. . .
Surfasb

2
concurrencyquan trọng hơn asynchronous hành vi. Bạn có thể có asyncronous mà không cần đồng thời (nghĩa là nhiều luồng trên một CPU lõi đơn) asynchronouskhông phải là sự thay thế ngữ nghĩa cho concurrency.

5
@Jarrod: Thuần hoá không đồng pha là nhiều quan trọng hơn chỉ đơn thuần thuần hóa đồng thời cho chính xác lý do bạn đề cập đến: đồng thời chỉ là một loại đặc biệt khó khăn của sự không đồng bộ. Phần khó của đồng thời không phải là khía cạnh "mọi thứ xảy ra cùng một lúc" của nó và thực tế, đồng thời thường chỉ được mô phỏng đồng thời , ví dụ, đa nhiệm không hợp tác thông qua việc cắt thời gian. Phần khó khăn là sử dụng hiệu quả các tài nguyên mà không chặn, treo, bế tắc và không viết ra các chương trình khó có thể lý giải về cục bộ.
Eric Lippert

"Đồng thời thường chỉ được mô phỏng đồng thời, ví dụ, đa nhiệm không hợp tác thông qua việc cắt thời gian": theo cách hiểu của tôi đây vẫn là đồng thời (đúng), có thể bạn muốn nói đó không phải là song song?
Giorgio

46

Nó ngày càng trở nên quan trọng hơn khi các bộ xử lý hiện đại ngày càng có nhiều lõi. Một thập kỷ trước, hầu hết các máy tính hiện tại chỉ có một bộ xử lý duy nhất, vì vậy đa luồng chỉ quan trọng trên các ứng dụng máy chủ cao cấp. Ngày nay, ngay cả máy tính xách tay cơ bản cũng có bộ xử lý đa lõi. Trong một vài năm, ngay cả các thiết bị di động ... Vì vậy, ngày càng cần nhiều mã hơn để sử dụng các lợi thế hiệu suất tiềm năng của đồng thời và để chạy chính xác trong môi trường đa luồng.


3
+1: Quan trọng hơn bao giờ hết. Cũng cần nhớ rằng trong một thiết kế hệ thống, bạn cũng có thể nhận được những lợi ích của đa luồng chỉ bằng cách phân vùng công việc để có nhiều quy trình thực hiện nó.
Scott C Wilson

11
Khá nhiều thiết bị di động đã có bộ xử lý đa lõi!
Che Jami

3
Tôi cho rằng đa luồng đã rất quan trọng kể từ khi hệ thống chia sẻ lần đầu tiên được xây dựng. Có nhiều bộ xử lý / lõi chỉ cần thêm một chiều hiệu quả mới để có nhiều luồng.
jwernerny

Có lẽ (đặc biệt là trên thiết bị di động) chủ đề là một ý tưởng tồi. HĐH có lẽ nên xử lý tối ưu hóa việc sử dụng các lõi mà không gặp lỗi mã người dùng khi thực hiện phân luồng. Có rất ít ứng dụng mà một người dùng bình thường có quyền truy cập vào nhu cầu đó hoặc sẽ có lợi cho nhiều người. Ngoại lệ duy nhất là (các ứng dụng đồ họa cao cấp / công cụ dành cho nhà phát triển / mô hình thời tiết / máy chủ Web (và các dịch vụ liên quan)) tất cả các ứng dụng chuyên dụng rất cao cấp.
Martin York

1
@ Tux-D, rất có thể bạn có một trò chơi trên thiết bị di động sử dụng nhiều lõi. Đó không phải là một cái gì đó đặc biệt.
Whitequark

28

Nhìn chung, đa luồng đã khá quan trọng và sẽ chỉ trở nên quan trọng hơn trong vài năm tới (như Péter Török) đã chỉ ra - đó là cách các bộ xử lý sẽ mở rộng cho tương lai có thể thấy được (nhiều lõi hơn thay vì MHz cao hơn) .

Tuy nhiên, trong trường hợp của bạn, bạn dường như làm việc chủ yếu với các ứng dụng web. Các ứng dụng web, về bản chất, là đa luồng do cách máy chủ web của bạn xử lý các yêu cầu cho mỗi người dùng (tức là song song). Mặc dù có lẽ bạn cần phải hiểu đồng thời và an toàn luồng (đặc biệt là khi xử lý bộ nhớ cache và dữ liệu được chia sẻ khác), tôi nghi ngờ bạn sẽ gặp quá nhiều trường hợp có lợi cho mã đa ứng dụng web trong nội bộ (tức là nhiều nhân viên chủ đề theo yêu cầu). Theo nghĩa đó, tôi nghĩ việc trở thành một chuyên gia về đa luồng là không thực sự cần thiết cho một nhà phát triển web. Nó thường được hỏi trong các cuộc phỏng vấn, bởi vì đây là một chủ đề khá khó và cũng bởi vì nhiều người phỏng vấn chỉ cần google một vài câu hỏi 10 phút trước khi bạn đến đó.


+1 cho lưu ý rằng người đăng là một nhà phát triển web và hầu hết các bộ chứa máy chủ web thực hiện một số lượng lớn công việc đa luồng cho bạn. Không phải là nó loại bỏ sự cần thiết trong một số trường hợp, nhưng 99% mã điều khiển đa luồng thời gian không phải là cải tiến hiệu suất lớn nhất cho một cuộc gọi MVC.
Mufasa

19

Đa luồng là cá trích đỏ. Đa luồng là một chi tiết triển khai cho vấn đề thực sự là Đồng thời . Không phải tất cả các chương trình luồng là đồng thời vì khóa và những gì không.

Chủ đề chỉ là một mô hình và mô hình thực hiện để thực hiện concurrentcác chương trình.

Chẳng hạn, bạn có thể viết phần mềm có khả năng mở rộng và chịu lỗi cao mà không cần thực hiện bất kỳ đa luồng nào trong các ngôn ngữ như Erlang.


+1 mặc dù tôi vẫn nghĩ Erlang là đa luồng; cộng đồng chỉ định nghĩa lại từ "luồng" để phụ thuộc vào trạng thái chia sẻ có thể thay đổi và do đó tự phân biệt với nó.
Dan

1
Theo mặc định, Erlang VM sử dụng 1 luồng cho mỗi CPU, nhưng với tư cách là nhà phát triển Erlang, bạn không có quyền truy cập vào các luồng hệ điều hành cơ bản chỉ các quy trình trọng lượng nhẹ mà Erlang VM cung cấp.

10

Tôi nhận được một vài câu hỏi về đa luồng trong các cuộc phỏng vấn ...

Vâng, để vượt qua các cuộc phỏng vấn, đa luồng có thể khá quan trọng. Tự trích dẫn , "khi phỏng vấn ứng viên cho nhóm của chúng tôi, tôi đặt câu hỏi đồng thời không phải vì những kỹ năng này quan trọng trong dự án của chúng tôi (nhưng không phải vì thế) mà vì tôi bằng cách nào đó giúp tôi dễ dàng đánh giá kiến ​​thức chung về ngôn ngữ mà chúng tôi sử dụng ..."


2
Có một số ý tưởng về đa luồng và lập trình đồng thời cũng thường chuyển sang một phương pháp phòng thủ, đó có thể là một điều rất tốt. Nếu bạn phải tính đến việc một cái gì đó hoàn toàn không liên quan trong quy trình của bạn có thể hoặc không thể ưu tiên một tuyên bố logic duy nhất và thực thi ở giữa mọi thứ khác, thì bạn phải lập kế hoạch cho khả năng đó. Việc triển khai đa luồng (trái ngược với các hình thức đồng thời khác) đơn giản có nghĩa là bạn có thêm gánh nặng về việc nó có thể làm gì đó với bất kỳ trạng thái nào không phải là luồng cục bộ.
một CVn

6

Hiểu cách tận dụng luồng để cải thiện hiệu suất là một kỹ năng quan trọng trong môi trường phần mềm ngày nay, đối với hầu hết các ngành công nghiệp và ứng dụng.

Tối thiểu, hiểu được các vấn đề liên quan đến đồng thời nên được đưa ra.

Lưu ý rõ ràng rằng không phải tất cả các ứng dụng hoặc môi trường sẽ có thể tận dụng lợi thế của nó, ví dụ như trong nhiều hệ thống nhúng. Tuy nhiên, có vẻ như bộ xử lý Atom (et al) dường như đang làm việc để thay đổi điều đó (đa lõi nhẹ bắt đầu trở nên phổ biến hơn).


4

Âm thanh như bạn đã viết mã đa luồng.

Hầu hết các ứng dụng web Java có thể xử lý nhiều yêu cầu cùng một lúc và chúng thực hiện điều này bằng cách sử dụng nhiều luồng.

Vì vậy, tôi muốn nói rằng điều quan trọng là phải biết những điều cơ bản ít nhất.


18
<nitpick> rõ ràng anh ấy không viết mã đa luồng, chỉ mã (một luồng) được chạy trong môi trường đa luồng. </ nitpick>
Péter Török

2

Nó vẫn quan trọng trong các tình huống mà bạn cần, nhưng cũng giống như nhiều thứ đang phát triển, nó là công cụ phù hợp cho công việc phù hợp. Tôi đã đi 3 năm mà không chạm vào luồng, bây giờ thực tế mọi thứ tôi làm đều có một số căn cứ trong đó. Với bộ xử lý đa lõi vẫn cần một luồng rất lớn, nhưng tất cả các lý do truyền thống vẫn còn hiệu lực, bạn vẫn muốn giao diện đáp ứng và bạn vẫn muốn có thể xử lý đồng bộ hóa và tiếp tục với những thứ khác cùng một lúc.


2

Câu trả lời ngắn gọn: Rất.

Câu trả lời dài hơn: Máy tính điện tử (dựa trên bóng bán dẫn) đang nhanh chóng tiếp cận các giới hạn vật lý của công nghệ. Việc ép nhiều đồng hồ ra khỏi mỗi lõi càng trở nên khó khăn hơn trong khi quản lý sự sinh nhiệt và hiệu ứng lượng tử của các mạch siêu nhỏ (các đường mạch đã được đặt rất gần nhau trên các chip hiện đại mà một hiệu ứng gọi là "đường hầm lượng tử" có thể tạo ra một điện tử "nhảy các rãnh" từ mạch này sang mạch khác, mà không cần các điều kiện thích hợp cho hồ quang điện truyền thống); vì vậy, hầu như tất cả các nhà sản xuất chip thay vì tập trung vào việc làm cho mỗi đồng hồ có thể làm được nhiều hơn, bằng cách đặt thêm "đơn vị thực thi" vào mỗi CPU. Sau đó, thay vì máy tính chỉ làm một việc trên mỗi đồng hồ, nó có thể thực hiện 2, hoặc 4 hoặc thậm chí 8. Intel có "HyperThreading", về cơ bản phân tách một lõi CPU thành hai bộ xử lý logic (với một số hạn chế). Hầu như tất cả các nhà sản xuất đều đặt ít nhất hai lõi CPU riêng biệt vào một chip CPU và tiêu chuẩn vàng hiện tại cho CPU máy tính để bàn là bốn lõi cho mỗi chip. Có thể sử dụng tám chip CPU, có các bo mạch chủ máy chủ được thiết kế cho bộ xử lý "lõi tứ" (16 EU cộng với HT tùy chọn) và thế hệ CPU tiếp theo có thể có sáu hoặc tám mỗi chip.

Kết quả của tất cả những điều này là, để tận dụng tối đa cách máy tính đạt được sức mạnh tính toán, bạn phải có khả năng cho phép máy tính "phân chia và chinh phục" chương trình của bạn. Các ngôn ngữ được quản lý có ít nhất một luồng xử lý quản lý bộ nhớ riêng biệt với chương trình của bạn. Một số cũng có các luồng "chuyển tiếp" xử lý interop COM / OLE (càng nhiều để bảo vệ "hộp cát" được quản lý như đối với hiệu suất). Mặc dù vậy, bạn thực sự phải bắt đầu suy nghĩ về cách chương trình của bạn có thể làm nhiều việc cùng một lúc và kiến ​​trúc chương trình của bạn với các tính năng được thiết kế để cho phép các phần của chương trình được xử lý không đồng bộ. Người dùng Windows và Windows, thực tế sẽ mong đợi chương trình của bạn thực hiện các tác vụ dài, phức tạp trong các luồng nền, giữ cho giao diện người dùng của chương trình của bạn (chạy trong luồng chính của chương trình) "phản hồi" với vòng lặp thông báo Windows. Rõ ràng, các vấn đề có giải pháp song song (như sắp xếp) là các ứng cử viên tự nhiên, nhưng có một số lượng hữu hạn các loại vấn đề được hưởng lợi từ việc song song hóa.


1

Chỉ là một cảnh báo về đa luồng: Nhiều chủ đề không có nghĩa là hiệu quả tốt hơn. Nếu không được quản lý đúng cách, chúng có thể làm chậm hệ thống. Diễn viên của Scala cải thiện việc phân luồng của Java và tối đa hóa việc sử dụng hệ thống (được đề cập là bạn là nhà phát triển Java).

EDIT: Đây là một số điều cần lưu ý về những nhược điểm của đa luồng:

  • giao thoa các luồng với nhau khi chia sẻ tài nguyên phần cứng
  • Thời gian thực hiện của một luồng không được cải thiện nhưng có thể bị suy giảm, ngay cả khi chỉ có một luồng đang thực thi. Điều này là do tần số chậm hơn và / hoặc các giai đoạn đường ống bổ sung cần thiết để phù hợp với phần cứng chuyển mạch.
  • Hỗ trợ phần cứng cho đa luồng được hiển thị nhiều hơn đối với phần mềm, do đó yêu cầu nhiều thay đổi hơn đối với cả chương trình ứng dụng và hệ điều hành so với Đa xử lý.
  • Khó khăn trong việc quản lý đồng thời.
  • Khó kiểm tra.

Ngoài ra, liên kết này có thể là một số trợ giúp về cùng.


2
Điều này dường như không trả lời câu hỏi của OP: - /
Péter Török

Mặc dù vậy, nó cung cấp một cái nhìn cấp cao nhất (hầu hết) của luồng. Một điều cần xem xét trước khi đi sâu vào đa luồng.
c0da

@ c0da Stack Exchange không phải là một bảng thảo luận: câu trả lời sẽ trực tiếp trả lời câu hỏi. Bạn có thể mở rộng câu trả lời của mình để đưa nó trở lại với những gì người hỏi đang tìm kiếm không?

1

Điều này khiến tôi tự hỏi rằng Multithreading quan trọng như thế nào trong kịch bản ngành hiện tại?

Trong các lĩnh vực quan trọng về hiệu năng, nơi hiệu suất không đến từ mã của bên thứ ba thực hiện công việc nặng nhọc, mà là của chúng tôi, sau đó tôi có xu hướng xem xét mọi thứ theo thứ tự quan trọng này từ góc độ CPU (GPU là ký tự đại diện tôi đã giành được đi vào):

  1. Hiệu quả bộ nhớ (ví dụ: địa phương của tài liệu tham khảo).
  2. Thuật toán
  3. Đa luồng
  4. SIMD
  5. Tối ưu hóa khác (gợi ý dự đoán nhánh tĩnh, ví dụ)

Lưu ý rằng đây là danh sách không chỉ dựa trên tầm quan trọng mà còn rất nhiều động lực khác như tác động của chúng đối với việc bảo trì, chúng đơn giản như thế nào (nếu không, đáng để xem xét trước), tương tác của chúng với những người khác trong danh sách, v.v.

Hiệu quả bộ nhớ

Hầu hết có thể ngạc nhiên về sự lựa chọn của tôi về hiệu quả bộ nhớ so với thuật toán. Đó là vì hiệu quả bộ nhớ tương tác với tất cả 4 mục khác trong danh sách này và đó là vì việc xem xét nó thường rất nhiều trong danh mục "thiết kế" thay vì danh mục "triển khai". Phải thừa nhận rằng có một chút vấn đề về con gà hoặc trứng ở đây vì hiểu được hiệu quả bộ nhớ thường yêu cầu xem xét tất cả 4 mục trong danh sách, trong khi cả 4 mục khác cũng yêu cầu xem xét hiệu quả bộ nhớ. Tuy nhiên, đó là trung tâm của mọi thứ.

Ví dụ: nếu chúng ta có nhu cầu về cấu trúc dữ liệu cung cấp truy cập tuần tự theo thời gian tuyến tính và chèn vào thời gian liên tục ở phía sau và không có gì khác cho các phần tử nhỏ, thì lựa chọn ngây thơ ở đây sẽ là một danh sách được liên kết. Đó là coi thường hiệu quả bộ nhớ. Khi chúng ta xem xét hiệu quả bộ nhớ trong hỗn hợp, cuối cùng chúng ta sẽ chọn các cấu trúc liền kề hơn trong kịch bản này, như các cấu trúc dựa trên mảng có thể phát triển hoặc các nút liền kề hơn (ví dụ: lưu trữ 128 phần tử trong một nút) được liên kết với nhau hoặc ít nhất là một danh sách liên kết được hỗ trợ bởi một phân bổ hồ bơi. Chúng có một lợi thế đáng kể mặc dù có cùng độ phức tạp thuật toán. Tương tự như vậy, chúng ta thường chọn quicksort của một mảng trên sắp xếp hợp nhất mặc dù độ phức tạp thuật toán kém hơn đơn giản chỉ vì hiệu quả bộ nhớ.

Tương tự như vậy, chúng ta không thể có đa luồng hiệu quả nếu các mẫu truy cập bộ nhớ của chúng ta quá nhỏ và phân tán trong tự nhiên đến mức cuối cùng chúng ta tối đa hóa lượng chia sẻ sai trong khi khóa ở mức độ chi tiết nhất trong mã. Vì vậy, hiệu quả bộ nhớ nhân lên hiệu suất đa luồng. Đó là một điều kiện tiên quyết để có được hầu hết các chủ đề.

Mỗi một mục ở trên trong danh sách đều có sự tương tác phức tạp với dữ liệu và tập trung vào cách thức dữ liệu được trình bày cuối cùng nằm trong tĩnh mạch của hiệu quả bộ nhớ. Mỗi một trong những điều trên có thể bị tắc nghẽn với cách thể hiện hoặc truy cập dữ liệu không phù hợp.

Một lý do khác khiến hiệu quả bộ nhớ rất quan trọng là nó có thể áp dụng trong toàn bộ cơ sở mã. Nói chung khi mọi người tưởng tượng rằng sự thiếu hiệu quả tích lũy từ các phần nhỏ của công việc ở đây và đó, đó là một dấu hiệu cho thấy họ cần phải lấy một hồ sơ. Tuy nhiên, các trường có độ trễ thấp hoặc những trường xử lý phần cứng rất hạn chế sẽ thực sự tìm thấy, ngay cả sau khi định hình, các phiên chỉ ra không có điểm nóng rõ ràng (chỉ phân tán khắp nơi) trong một cơ sở mã không hiệu quả với cách phân bổ, sao chép và truy cập bộ nhớ. Thông thường, đây là khoảng thời gian duy nhất toàn bộ một cơ sở mã có thể dễ bị ảnh hưởng bởi hiệu suất có thể dẫn đến một bộ tiêu chuẩn hoàn toàn mới được áp dụng trong toàn bộ cơ sở mã và hiệu quả bộ nhớ thường là trọng tâm của nó.

Thuật toán

Điều này khá giống nhau, vì sự lựa chọn trong thuật toán sắp xếp có thể tạo ra sự khác biệt giữa một đầu vào lớn mất hàng tháng để sắp xếp so với giây để sắp xếp. Nó tạo ra tác động lớn nhất của tất cả nếu sự lựa chọn nằm giữa các thuật toán bậc hai hoặc bậc ba thực sự và một thuật toán tuyến tính, hoặc giữa tuyến tính và logarit hoặc hằng số, ít nhất là cho đến khi chúng ta có 1.000.000 máy lõi (trong trường hợp đó là bộ nhớ hiệu quả sẽ trở nên quan trọng hơn nữa).

Tuy nhiên, nó không đứng đầu danh sách cá nhân của tôi, vì bất kỳ ai có năng lực trong lĩnh vực của họ đều biết sử dụng cấu trúc gia tốc để loại bỏ sự bực bội, ví dụ: Chúng tôi bị bão hòa bởi kiến ​​thức thuật toán và biết những thứ như sử dụng biến thể của một trie như một cây cơ số cho các tìm kiếm dựa trên tiền tố là công cụ bé. Thiếu loại kiến ​​thức cơ bản về lĩnh vực chúng tôi đang làm việc, thì hiệu quả thuật toán chắc chắn sẽ tăng lên hàng đầu, nhưng thường thì hiệu quả thuật toán là không đáng kể.

Ngoài ra, việc phát minh ra các thuật toán mới có thể là một điều cần thiết trong một số lĩnh vực (ví dụ: trong xử lý lưới tôi đã phải phát minh ra hàng trăm vì chúng không tồn tại trước đó hoặc việc triển khai các tính năng tương tự trong các sản phẩm khác là bí mật độc quyền, không được công bố trong một bài báo ). Tuy nhiên, một khi chúng ta vượt qua phần giải quyết vấn đề và tìm cách có được kết quả chính xác và một khi hiệu quả trở thành mục tiêu, cách duy nhất để thực sự đạt được nó là xem xét cách chúng ta tương tác với dữ liệu (bộ nhớ). Nếu không hiểu hiệu quả bộ nhớ, thuật toán mới có thể trở nên phức tạp không cần thiết với những nỗ lực vô ích để làm cho nó nhanh hơn, khi điều duy nhất nó cần là xem xét thêm một chút về hiệu quả bộ nhớ để mang lại một thuật toán đơn giản hơn, thanh lịch hơn.

Cuối cùng, các thuật toán có xu hướng nằm trong danh mục "triển khai" hơn là hiệu quả bộ nhớ. Chúng thường dễ dàng cải thiện hơn trong nhận thức ngay cả với thuật toán tối ưu phụ được sử dụng ban đầu. Ví dụ, thuật toán xử lý ảnh kém hơn thường chỉ được thực hiện ở một vị trí cục bộ trong cơ sở mã. Nó có thể được trao đổi với một cái tốt hơn sau này. Tuy nhiên, nếu tất cả các thuật toán xử lý hình ảnh được gắn với một Pixelgiao diện có biểu diễn bộ nhớ tối ưu phụ, nhưng cách duy nhất để sửa nó là thay đổi cách thể hiện nhiều pixel (chứ không phải một pixel), thì chúng ta thường SOL và sẽ phải viết lại hoàn toàn codebase theo hướngImagegiao diện. Một loại điều tương tự dành cho việc thay thế một thuật toán sắp xếp - nó thường là một chi tiết triển khai, trong khi một sự thay đổi hoàn toàn đối với biểu diễn cơ bản của dữ liệu được sắp xếp hoặc cách nó truyền qua các thông điệp có thể yêu cầu các giao diện được thiết kế lại.

Đa luồng

Đa luồng là một khó khăn trong bối cảnh hiệu suất vì nó là tối ưu hóa ở cấp độ vi mô theo các đặc điểm phần cứng, nhưng phần cứng của chúng tôi thực sự mở rộng theo hướng đó. Tôi đã có các đồng nghiệp có 32 lõi (tôi chỉ có 4).

Tuy nhiên, mulithreading là một trong những tối ưu hóa vi mô nguy hiểm nhất có thể được một chuyên gia biết đến nếu mục đích được sử dụng để tăng tốc phần mềm. Điều kiện cuộc đua gần như là lỗi nghiêm trọng nhất có thể xảy ra, vì bản chất nó không rõ ràng (có thể chỉ xuất hiện một vài tháng một lần trên máy của nhà phát triển vào thời điểm bất tiện nhất bên ngoài bối cảnh gỡ lỗi). Vì vậy, nó được cho là sự xuống cấp tiêu cực nhất về khả năng bảo trì và tính chính xác tiềm năng của mã trong số này, đặc biệt là do các lỗi liên quan đến đa luồng có thể dễ dàng bay theo radar ngay cả khi thử nghiệm cẩn thận nhất.

Tuy nhiên, nó trở nên rất quan trọng. Mặc dù có thể vẫn không phải lúc nào cũng chiếm ưu thế như hiệu quả bộ nhớ (đôi khi có thể khiến mọi thứ nhanh hơn gấp trăm lần) với số lượng lõi chúng ta có bây giờ, chúng ta đang thấy ngày càng nhiều lõi. Tất nhiên, ngay cả với các máy 100 lõi, tôi vẫn đặt hiệu quả bộ nhớ lên đầu danh sách, vì hiệu quả của luồng nói chung là không thể nếu không có nó. Một chương trình có thể sử dụng hàng trăm luồng trên một máy như vậy và vẫn chậm khi thiếu các mẫu truy cập và biểu diễn bộ nhớ hiệu quả (sẽ liên kết với các mẫu khóa).

SIMD

SIMD cũng hơi khó xử vì các thanh ghi thực sự ngày càng rộng hơn, với các kế hoạch sẽ còn rộng hơn nữa. Ban đầu chúng tôi đã thấy các thanh ghi MMX 64 bit, sau đó là các thanh ghi XMM 128 bit có khả năng hoạt động song song 4 SPFP. Bây giờ chúng ta đang thấy các thanh ghi YMM 256 bit có khả năng 8 song song. Và đã có kế hoạch thay thế cho các thanh ghi 512 bit cho phép 16 thanh ghi song song.

Chúng sẽ tương tác và nhân lên với hiệu quả của đa luồng. Tuy nhiên, SIMD có thể làm giảm khả năng bảo trì cũng giống như đa luồng. Mặc dù các lỗi liên quan đến chúng không nhất thiết phải khó tái tạo và sửa chữa như tình trạng bế tắc hoặc cuộc đua, tính di động rất khó xử và đảm bảo rằng mã có thể chạy trên máy của mọi người (và sử dụng các hướng dẫn phù hợp dựa trên khả năng phần cứng của họ) vụng về.

Một điều nữa là trong khi các trình biên dịch ngày nay thường không đánh bại mã SIMD được viết một cách thành thạo, thì chúng dễ dàng đánh bại các nỗ lực ngây thơ. Chúng có thể cải thiện đến mức chúng ta không còn phải thực hiện thủ công hoặc ít nhất là không cần thủ công để viết nội tại hoặc mã lắp ráp thẳng (có lẽ chỉ là một chút hướng dẫn của con người).

Mặc dù vậy, một lần nữa, không có bố cục bộ nhớ hiệu quả cho xử lý véc tơ, SIMD là vô dụng. Chúng tôi cuối cùng chỉ tải một trường vô hướng vào một thanh ghi rộng chỉ để thực hiện một thao tác trên nó. Trọng tâm của tất cả các mục này là sự phụ thuộc vào bố trí bộ nhớ để thực sự hiệu quả.

Tối ưu hóa khác

Đây thường là những gì tôi muốn đề nghị chúng ta bắt đầu gọi "vi mô" ngày nay nếu từ này gợi ý không chỉ vượt ra ngoài trọng tâm thuật toán mà còn hướng tới những thay đổi có tác động rất nhỏ đến hiệu suất.

Thường cố gắng tối ưu hóa cho dự đoán nhánh đòi hỏi phải thay đổi thuật toán hoặc hiệu quả bộ nhớ, ví dụ: Nếu điều này chỉ được cố gắng thông qua gợi ý và sắp xếp lại mã để dự đoán tĩnh, điều đó chỉ có xu hướng cải thiện việc thực thi mã lần đầu tiên, khiến các hiệu ứng trở nên nghi ngờ nếu không thường xuyên hoàn toàn không đáng kể

Quay lại đa luồng cho hiệu suất

Vì vậy, dù sao, đa luồng quan trọng như thế nào từ bối cảnh hiệu suất? Trên máy 4 lõi của tôi, lý tưởng nhất có thể khiến mọi thứ nhanh hơn khoảng 5 lần (những gì tôi có thể nhận được với siêu phân luồng). Nó sẽ quan trọng hơn đáng kể đối với đồng nghiệp của tôi, người có 32 lõi. Và nó sẽ ngày càng trở nên quan trọng trong những năm tới.

Vì vậy, nó khá quan trọng. Nhưng thật vô ích khi chỉ ném một loạt các luồng vào vấn đề nếu hiệu quả bộ nhớ không có để cho phép các khóa được sử dụng một cách tiết kiệm, để giảm chia sẻ sai, v.v.

Đa luồng ngoài hiệu suất

Đa luồng không phải lúc nào cũng nói về hiệu suất tuyệt đối theo kiểu thông lượng đơn giản. Đôi khi, nó được sử dụng để cân bằng tải ngay cả với chi phí thông lượng có thể có để cải thiện khả năng phản hồi cho người dùng hoặc cho phép người dùng thực hiện đa nhiệm nhiều hơn mà không cần chờ mọi thứ kết thúc (ví dụ: tiếp tục duyệt trong khi tải xuống tệp).

Trong những trường hợp đó, tôi đề nghị rằng đa luồng tăng cao hơn nữa về phía trên (thậm chí có thể cao hơn hiệu quả bộ nhớ), vì đó là về thiết kế cuối của người dùng thay vì tận dụng tối đa phần cứng. Nó sẽ thường thống trị các thiết kế giao diện và cách chúng ta cấu trúc toàn bộ cơ sở mã của chúng ta trong các tình huống như vậy.

Khi chúng ta không chỉ đơn giản là song song một vòng lặp chặt chẽ truy cập vào một cấu trúc dữ liệu khổng lồ, đa luồng sẽ chuyển sang danh mục "thiết kế" thực sự khó khăn và thiết kế luôn vượt qua việc thực hiện.

Vì vậy, trong những trường hợp đó, tôi muốn nói rằng việc xem trước đa luồng là hoàn toàn quan trọng, thậm chí còn hơn cả việc truy cập và thể hiện bộ nhớ.


0

Lập trình đồng thời và song song là những gì đang trở nên quan trọng. Các luồng chỉ là một mô hình lập trình để thực hiện nhiều việc cùng một lúc (và không song song giả như trước đây trước khi có sự gia tăng của các bộ xử lý đa lõi). Đa luồng bị (IMHO khá) bị chỉ trích là phức tạp và nguy hiểm vì các luồng chia sẻ nhiều tài nguyên và lập trình viên chịu trách nhiệm làm cho chúng hợp tác. Nếu không, bạn sẽ kết thúc với những bế tắc khó gỡ lỗi.


0

Vì chúng tôi có thể cần liên hệ với nhiều ứng dụng bên ngoài, có thể có một số quy trình nền sẽ xảy ra khi tương tác hệ thống bên ngoài mất nhiều thời gian hơn và người dùng cuối không thể đợi cho đến khi quá trình hoàn tất. Vì vậy, đa luồng là quan trọng ..

chúng tôi đang sử dụng trong ứng dụng của mình, trước tiên chúng tôi cố gắng liên hệ với hệ thống bên ngoài nếu nó bị hỏng sau đó chúng tôi lưu yêu cầu trong Cơ sở dữ liệu và kéo dài một chuỗi để kết thúc quá trình trong backgound. Có thể yêu cầu trong hoạt động hàng loạt quá.


0

Trong lịch sử mọi người phải vật lộn bằng cách lập trình đa luồng bằng tay. Họ đã phải làm việc với tất cả các thành phần cốt lõi (chủ đề, semaphores, mutexes, lock, v.v.) trực tiếp.

Tất cả những nỗ lực này đã dẫn đến các ứng dụng có thể mở rộng quy mô bằng cách thêm cpus bổ sung vào một hệ thống. Khả năng mở rộng theo chiều dọc này bị giới hạn bởi "máy chủ lớn nhất tôi có thể mua".

Ngày nay tôi thấy một sự thay đổi theo hướng sử dụng nhiều khung và các mô hình thiết kế khác nhau cho thiết kế phần mềm. MapReduce là một mô hình như vậy được tập trung vào xử lý hàng loạt.

Mục tiêu là nhân rộng theo chiều ngang. Thêm nhiều máy chủ tiêu chuẩn thay vì mua máy chủ lớn hơn.

Điều đó nói rằng thực tế vẫn còn thực sự hiểu lập trình đa luồng là rất quan trọng. Tôi đã ở trong tình huống ai đó tạo ra một điều kiện cuộc đua và thậm chí không biết điều kiện cuộc đua là gì cho đến khi chúng tôi nhận thấy các lỗi lạ trong quá trình thử nghiệm.


-1

Máy của tôi có 8 lõi. Trong Trình quản lý tác vụ, tôi có 60 quy trình đang chạy. Một số, như VS, sử dụng tới 98 chủ đề. Outlook sử dụng 26. Tôi hy vọng phần lớn việc sử dụng bộ nhớ của tôi là các ngăn xếp được phân bổ cho từng luồng không hoạt động.

Cá nhân tôi đang chờ máy tính 300 lõi xuất hiện để tôi không phải chờ Outlook phản hồi. Tất nhiên sau đó Outlook sẽ sử dụng 301 chủ đề.

Đa luồng chỉ quan trọng nếu bạn đang xây dựng các hệ thống sẽ là quá trình quan trọng duy nhất trên máy tính tại một thời điểm cụ thể (ví dụ: các công cụ tính toán). Các ứng dụng máy tính để bàn có thể sẽ giúp người dùng ưu tiên bằng cách không sử dụng hết mọi lõi có sẵn. Các ứng dụng web sử dụng mô hình yêu cầu / phản hồi vốn đã đa luồng.

Nó quan trọng đối với các nhà thiết kế khung và ngôn ngữ, và các lập trình viên hệ thống phụ trợ - không quá nhiều đối với các nhà xây dựng ứng dụng. Hiểu một số khái niệm cơ bản như khóa và viết mã async có lẽ đáng giá.


Tôi sẽ thường xuyên đánh một cái gì đó trên một luồng nền như tải DB dài, nhưng rất hiếm khi tôi phải đối phó với các điều kiện đua hoặc khóa, v.v. (thực tế có lẽ không bao giờ)
Aran Mulholland
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.