Phần cứng / việc thực hiện có ảnh hưởng đến độ phức tạp thời gian / không gian của các thuật toán không?


32

Tôi thậm chí không phải là một sinh viên CS, vì vậy đây có thể là một câu hỏi ngu ngốc, nhưng xin vui lòng chịu đựng với tôi ...

Trong kỷ nguyên tiền máy tính, chúng ta chỉ có thể thực hiện một cấu trúc dữ liệu mảng với một cái gì đó giống như một mảng các ngăn kéo. Vì người ta phải định vị ngăn kéo với chỉ mục tương ứng trước khi trích xuất giá trị từ nó, độ phức tạp thời gian của tra cứu mảng là , giả sử tìm kiếm nhị phân.O(log(n))

Tuy nhiên, việc phát minh ra máy tính đã tạo ra một sự khác biệt lớn. Các máy tính hiện đại có thể đọc từ RAM của chúng nhanh đến mức bây giờ chúng ta coi độ phức tạp của thời gian tìm kiếm mảng là (thậm chí về mặt kỹ thuật không phải là trường hợp này, vì phải mất nhiều thời gian hơn để di chuyển thanh ghi qua một khoảng cách lớn hơn, v.v.)O(1)

Một ví dụ khác là từ điển Python. Mặc dù người ta có thể có được độ phức tạp truy cập từ điển của bằng phương pháp ma thuật quá tải bằng văn bản (hoặc xui xẻo, tức là các khóa có nhiều va chạm băm), nó thường được coi là . Trong trường hợp này, độ phức tạp thời gian phụ thuộc vào cả việc thực hiện bảng băm của từ điển Python và việc thực hiện các hàm băm của các khóa.O ( 1 )O(n)__hash__O(1)

Có phải điều này ngụ ý rằng phần cứng / thực hiện có thể ảnh hưởng đến độ phức tạp thời gian của các thuật toán? (Mặc dù cả hai ví dụ là về cấu trúc dữ liệu thay vì thuật toán, cái sau được xây dựng dựa trên cấu trúc trước và tôi chưa bao giờ nghe về sự phức tạp về thời gian của cấu trúc dữ liệu, vì vậy tôi đang sử dụng thuật ngữ "thuật toán" ở đây)

Đối với tôi, các thuật toán là trừu tượng và mang tính khái niệm, những thuộc tính như độ phức tạp thời gian / không gian không bị ảnh hưởng bởi liệu chúng có được thực hiện theo một cách cụ thể không, nhưng chúng có phải không?


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


42

Chắc chắn rồi. Chắc chắn rồi. Đây là cách để hòa giải sự khó chịu của bạn.

Khi chúng tôi phân tích thời gian chạy của các thuật toán, chúng tôi thực hiện nó đối với một mô hình tính toán cụ thể . Mô hình tính toán chỉ định những thứ như thời gian cần thiết để thực hiện từng thao tác cơ bản (là thời gian tra cứu mảng hay thời gian ?). Thời gian chạy của thuật toán có thể phụ thuộc vào mô hình tính toán.O ( 1 )O(logn)O(1)

Khi bạn đã chọn một mô hình tính toán, việc phân tích thuật toán là một bài tập toán học hoàn toàn trừu tượng, mang tính khái niệm, không còn phụ thuộc vào phần cứng.

Tuy nhiên, trong thực tế, chúng ta thường muốn chọn một mô hình tính toán phản ánh thực tế của phần cứng của chúng ta - ít nhất là ở mức độ hợp lý. Vì vậy, nếu phần cứng thay đổi, chúng tôi có thể quyết định phân tích các thuật toán của chúng tôi theo một mô hình tính toán khác phù hợp hơn với phần cứng mới. Đó là cách phần cứng có thể ảnh hưởng đến thời gian chạy.

Lý do điều này không rõ ràng là vì, trong các lớp giới thiệu, chúng ta thường không nói về mô hình tính toán. Chúng tôi chỉ ngầm đưa ra một số giả định, mà không bao giờ làm cho chúng rõ ràng. Điều đó hợp lý, cho các mục đích sư phạm, nhưng nó có chi phí - nó che giấu khía cạnh phân tích này. Bây giờ bạn biết.


Như bạn đã nói, chúng tôi sử dụng mô hình truy cập ngẫu nhiên làm mô hình tính toán nhưng khi chúng tôi sử dụng GPU cho một số tính toán nhất định thì độ phức tạp thời gian đối với một số thuật toán thay đổi khi nó sử dụng các hướng dẫn SIMD.
Sâu Joshi

6
Cũng lưu ý rằng ký hiệu O () là một giới hạn trên. Ngay cả khi bạn sử dụng phép tương tự ngăn kéo, việc tìm một ngăn kéo ở kích thước giới hạn (bộ nhớ thực bị giới hạn về kích thước) tòa nhà sẽ mất thời gian O (1). Ngay cả khi bạn mất 20 phút để đến ngăn kéo xa nhất (tất cả các bộ nhớ cache bị mất và bạn thậm chí phải tải dữ liệu từ trao đổi) vẫn còn O (1) vì 20 phút sẽ là hằng số ẩn của bạn để truy cập bộ nhớ.
Goswin von Brederlow

2
Đối với một ví dụ thực tế về những gì @GoswinvonBrederlow đang nói, hãy xem xét rằng việc tìm kiếm một giá trị với bản đồ băm có hiệu quả là . Tìm kiếm một giá trị trong một mảng không có thứ tự là . Tuy nhiên, trong một ứng dụng thực tế tôi đã viết gần đây, sử dụng một mảng nhanh hơn so với sử dụng bản đồ băm. Nó nhanh hơn bởi vì tôi có một số lượng nhỏ các giá trị để tìm kiếm (dưới 10) và chi phí thực hiện hàm băm và thuật toán hashmap thực sự lớn hơn chi phí chỉ bằng cách bắt buộc tìm kiếm mảng! Đối với các vấn đề có kích thước thực tế, tôi đã tăng mã của mình theo hệ số 3 theo cách này. O ( n )O(1)O(n)
Cort Ammon - Phục hồi Monica

1
@CortAmmon: Ngay cả trên một mảng lớn, sử dụng tìm kiếm tuyến tính có thể nhanh hơn sử dụng bản đồ băm nếu tất cả ngoại trừ một vài yếu tố trên đang tìm kiếm rất gần khi bắt đầu. Ví dụ: nếu 50% phần tử khớp với phần tử thứ nhất, 25% khớp với phần tử thứ hai, 12,5% khớp với phần tử thứ ba, v.v. ngoại trừ một phần tử lẻ sẽ khớp với phần tử có thể ở bất kỳ đâu trong mảng, số lượng so sánh dự kiến ​​sẽ thực hiện tra cứu M trên danh sách kích thước N sẽ là 2M + N.
supercat

5
@DeepJoshi Hướng dẫn SIMD không thay đổi độ phức tạp của thuật toán. Họ chỉ thay đổi hằng số nhân.
Gilles 'SO- đừng trở nên xấu xa'

5

Tôi nghĩ rằng có một sự hiểu lầm cơ bản trong câu hỏi. Bạn so sánh một người tìm một đối tượng trong danh sách được sắp xếp (ví dụ: một trang cụ thể trong sách, với số của nó) với một máy tính đang tìm kiếm một mục từ một mảng.

Lý do mà cựu đòi hỏi thời gian và sau này cần có thời gian là không rằng máy tính là quá nhanh đến nỗi nó có thể thực hiện tìm kiếm nhị phân trong chớp mắt. Thay vào đó, đó là vì máy tính hoàn toàn không sử dụng tìm kiếm nhị phân. Máy tính có một cơ chế để lấy trực tiếp các mục từ mảng mà không cần tìm kiếm. Để lấy lại nội dung của một ô mảng, máy tính chỉ cần nói với bộ điều khiển bộ nhớ tương tự "Cho tôi trang mười bảy", bộ điều khiển bộ nhớ đặt các điện áp trên dây địa chỉ thành biểu diễn nhị phân của mười bảy và dữ liệu quay trở lại.O ( 1 )O(logn)O(1)

Vì vậy, vâng, phần cứng (tức là mô hình tính toán) không ảnh hưởng đến thời gian chạy của thuật toán, như DW giải thích , nhưng đó không phải là ví dụ về truy cập mảng của bạn dựa trên.


2
Để công bằng, bạn đã bỏ qua tất cả các phần ở giữa "bộ điều khiển bộ nhớ đặt điện áp trên dây địa chỉ thành biểu diễn nhị phân của mười bảy" và "dữ liệu quay trở lại". Một trong những phần đó gần như chắc chắn một cây tìm kiếm nhị phân thuộc loại được mô tả bởi OP; nhưng dù sao nó cũng thực thi trong thời gian không đổi vì log n xấp xỉ 64, với tất cả n .
Quuxplusone

@Quuxplusone Phần nào của bộ nhớ sử dụng tìm kiếm nhị phân? Các dòng địa chỉ trực tiếp chọn các ô nhớ.
David Richerby

Chúng tôi đang hoạt động xa xa ngoài khu vực chuyên môn của tôi, nhưng những gì tôi đã cố gắng để ngụ ý là một bộ giải mã địa chỉ sẽ được thực hiện trong điều khoản của một cây demuxers . (Giả sử rằng chúng ta đang trực tiếp đánh bộ nhớ vật lý, bỏ qua bất kỳ biến chứng phụ mà đi kèm với bộ nhớ đệm .) Một lần nữa, tất cả các biến chứng phụ này chỉ cho biết thêm O(lg size-of-memory), tức là không đáng kể - nhưng đó là chính xác chút OP được hỏi về!
Quuxplusone

2

Không, phần cứng không ảnh hưởng đến sự phức tạp của các thuật toán.

Nhưng , nó ảnh hưởng đến việc lựa chọn thuật toán và nó có thể ảnh hưởng đến tính hữu ích của phân tích độ phức tạp đến mức phân tích trở nên vô nghĩa (hoặc chỉ đơn thuần là lợi ích học thuật).

Tìm ngăn kéo bên phải (khi truy cập một phần tử mảng) sử dụng thuật toán "mở phần tử N trực tiếp theo chỉ mục", chứ không phải thuật toán "tìm kiếm tuyến tính" hoặc "tìm kiếm nhị phân". Các thuật toán không thay đổi, nhưng sự lựa chọn.

Mặt khác, bản thân phân tích phức tạp, hay đúng hơn là ý nghĩa của nó, bị ảnh hưởng rất nhiều bởi phần cứng.

Nhiều thuật toán nổi bật nhờ phân tích độ phức tạp của chúng là những người thực hiện kém hoặc thậm chí vô dụng trong thực tế vì yếu tố hằng số không đáng kể hoàn toàn không đáng kể, nhưng chiếm ưu thế .

Hoặc, bởi vì các giả định đã từng đúng (hoặc chủ yếu là đúng) không còn tồn tại nữa. Chẳng hạn như, ví dụ, mọi thao tác hầu hết đều giống nhau (chỉ có những khác biệt nhỏ không quan trọng) hoặc không tạo ra sự khác biệt về vị trí bộ nhớ mà bạn truy cập theo thứ tự nào. Bằng cách phân tích độ phức tạp, bạn có thể kết luận rằng một số thuật toán vượt trội hơn rất nhiều vì nó chỉ cần rất nhiều thao tác. Trong thực tế, bạn có thể thấy rằng mỗi thao tác gây ra lỗi bộ nhớ cache được bảo đảm (hoặc tệ hơn là lỗi trang), điều này giới thiệu một k quá lớn đến nỗi nó không còn đáng kể, mà chi phối mọi thứ.
Nếu thuật toán A mất 500 thao tác để xử lý một tập dữ liệu có kích thước nhất định và thuật toán B chỉ mất 5, nhưng B gây ra 5 lỗi, mỗi lần đốt hai mươi triệu chu kỳ, thì mặc dù những gì anaylsis hoặc thông thường có thể cho bạn biết, A vẫn tốt hơn.

Điều này đã dẫn đến những bất ngờ thú vị như ví dụ như trong Cuckoo Hashing vài năm trước. Đó là rất nhiều vượt trội bởi vì [danh sách dài các lợi ích]. Sau khi cường điệu hóa ra, hóa ra nó kém hơn rất nhiều vì nó đảm bảo hai lỗi bộ nhớ cache (lỗi, cho các tập dữ liệu lớn hơn) trên mỗi lần truy cập.

Tương tự đã xảy ra để xác định và xử lý tập hợp con của dữ liệu. Thông thường, giải pháp chính xác hiện nay là: "chỉ cần làm tất cả" , tức là thay vì tìm ra những gì bạn cần phải làm và làm điều đó, hãy xử lý bộ dữ liệu hoàn chỉnh một cách tuyến tính ngay cả khi bạn có thể chỉ cần một nửa. Bởi vì, tin hay không, điều đó nhanh hơn do không có sự đánh giá sai về chi nhánh, không bỏ sót bộ nhớ cache, không có lỗi trang.
Cần đọc 8kB đầu tiên và 3kB cuối cùng của tệp 3MB? Chà, đọc tập tin hoàn chỉnh và vứt bỏ những gì bạn không muốn, bởi vì tìm kiếm ở giữa sẽ chậm hơn mười lần so với việc chỉ đọc những thứ hoàn chỉnh.

Sử dụng bản đồ vì nó có độ phức tạp logarit? Hoặc một bảng băm, có thời gian truy cập liên tục? Âm thanh liên tục tuyệt vời. Chà, đối với bất cứ thứ gì có ít hơn một nghìn thứ (tùy thuộc vào phần cứng, kích thước dữ liệu và mẫu truy cập), tìm kiếm tuyến tính có thể tốt hoặc tốt hơn. Sự ngạc nhiên.

Vì vậy, nó không phải là các thuật toán bị ảnh hưởng, mà là sự hữu ích và sự lựa chọn của chúng.

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.