logic 'chống phân mảnh' đơn giản mà giảm thiểu thay đổi?


8

biên tập:

Vì vậy, rõ ràng tôi đã không giải thích điều này tốt, vì vậy hãy để tôi thử lại với các ví dụ. Tôi có một 'ống' có kích thước nhất định với các tín hiệu được truyền qua nó tại các độ lệch đã cho. Các đường ống có thể bị phân mảnh với các tín hiệu ở các độ lệch khác nhau làm cho nó không thể phù hợp với tín hiệu mới. Tôi muốn một thuật toán sẽ cho tôi biết cách sắp xếp các tín hiệu để chống phân mảnh đường ống; nhưng với số lượng tín hiệu tối thiểu thực sự được di chuyển! Vì vậy, ví dụ ..

Giả sử tôi có một ống có kích thước 16. Nó có các tín hiệu sau với các kích thước và độ lệch được mô tả.

offset 0: A (size of 4; fills slots 0-3)
offset 5: C (size of 2, fills slot 5-6)
offset 8: B (size of 4, fills 8-11)
offset 14: D (size 2, fills 14-15)

Pipe: AAAA_CC_BBBB__DD

Trong trường hợp này, tôi có 1 vị trí mở tại offset 4 & 7 và hai vị trí ở phần bù 12-13. Bây giờ hãy nói rằng tôi muốn thêm tín hiệu kích thước 4 vào đường ống này. Không có không gian liên tục cho nó bây giờ, nhưng tôi biết tôi có đủ không gian cho nó nếu tôi chống phân mảnh. Giải pháp 'hiển nhiên' là nhóm tất cả các tín hiệu lại với nhau ở 'đỉnh' như thế này:

offset 0:  A (size 4, fills 0-3)
offset 4:  B (size 4, fills 4-7)
offset 8:  C (size 2, fills 8-9)
offset 10: D (size 2, fills 10-11)

Pipe: AAAABBBBCCDD____

Điều này để lại các khe 12-15 miễn phí cho tín hiệu mới của tôi. Tuy nhiên, để làm điều này tôi đã định vị lại 3 tín hiệu (BD). Đối với mỗi tín hiệu tôi di chuyển, tôi phải gửi các lệnh xuống phần cứng và chờ một khoảng thời gian không hề nhỏ.

Nếu tôi thông minh hơn tôi có thể nhận ra có một sự chấp thuận khác. Tôi có thể định vị lại như thế này:

offset 0:  A(size 4, fills 0-3)
offset 8:  B(size 4, fills 8-11)
offset 12: C(size 2, fills 12-13)
offset 14: D(size 2, fills 14-15).

Pipe: AAAA____BBBBCCDD

Bây giờ tôi có thể điều chỉnh tín hiệu mới của mình trong các lần bù 4-7; VÀ tôi chỉ phải định vị lại một tín hiệu (B). Do đó tiết kiệm cuộc gọi phần cứng.

Tôi tự hỏi nếu có một thuật toán tốt để phát hiện các chỗ ngồi như thế này; nơi tôi có thể 'lắp' tín hiệu vào đường ống với số lượng tín hiệu tối thiểu được di chuyển. Apta thta đến với tâm trí là một N! thuật toán; về cơ bản là hướng đến "tạo ra mọi phân phối có thể, tính toán số lần di chuyển mà nó dẫn đến". Tôi đang cho một sự chấp thuận nhanh hơn.

Sự chấp thuận không nhất thiết phải hoàn hảo 100%, tôi chủ yếu tìm cách giảm thiểu trường hợp trung bình, miễn là trường hợp xấu nhất không được thực hiện quá khủng khiếp. Tôi biết rằng tôi sẽ không bao giờ có nhiều hơn 255 tín hiệu trên một đường ống nhất định; vì vậy tôi có thể 'thoát khỏi' với N! tệ như âm thanh đó Tôi cũng biết kích thước của mỗi tín hiệu là công suất bằng 2, cũng như kích thước đường ống.

Ngoài ra, có bất kỳ thuật toán sáng chói để đặt các tín hiệu giảm thiểu sự phân mảnh?


Câu hỏi đã được trả lời; xem bên dưới.

Tôi muốn tiết lộ một chút về câu trả lời để giải thích rõ hơn về việc phân mảnh sẽ xảy ra như thế nào đối với bất kỳ ai đọc; bạn thân giải thích nó tôi muốn chỉ ra một cách tiếp cận đơn giản hơn để khái niệm hóa và giải thích phần phân mảnh chi tiết hơn vì đó là câu hỏi ban đầu.

Tôi đang giải thích về sự chấp thuận của mình, đó là một cách tiếp cận hơi khác / đơn giản hơn nhưng vẫn giữ hiệu quả khái niệm 'bạn thân'. Tôi không tính toán trước các khối hoặc dán nhãn cho chúng, đây là quá nhiều nỗ lực để thực hiện và duy trì. Đối với tôi, chi phí CPU để tính toán tín hiệu sẽ đi đâu là khá nhỏ so với việc đặt / xóa tín hiệu thực tế; vì vậy tôi có thể đủ khả năng để mất một lượng CPU nhỏ, tuyến tính bằng cách không tính toán trước để đơn giản hóa logic của mình. Vì vậy, quá trình là:

để chèn:

Tất cả các tín hiệu được giữ trong các ranh giới tín hiệu bằng với kích thước tín hiệu, do đó tín hiệu sẽ bắt đầu ở phần bù trong đó% offestize = 0. Để bù đắp Actuall, chúng tôi đi qua và tìm ra các khoảng thời gian giữ liên kết này. Vì vậy, nếu tín hiệu của tôi là kích thước 4 trên ống kích thước 16, tôi sẽ xem xét các khoảng 0-4, 5-7, 8-11, 12-15.

Đối với mỗi khoảng thời gian kiểm tra nếu tất cả không gian trong khoảng đó là miễn phí. Trong trường hợp đơn giản, chúng ta có một khoảng không có tín hiệu trong đó và chúng ta chỉ đặt tín hiệu ở khoảng đó. Quan trọng, chúng tôi xem xét các khoảng theo thứ tự và đặt tín hiệu của chúng tôi trong khoảng miễn phí đầu tiên , điều này đảm bảo chúng tôi phá vỡ 'khối' nhỏ nhất có thể (sử dụng thuật ngữ bạn bè) khi chúng tôi thêm tín hiệu của mình. Điều này nên tương đương với sự chấp thuận của bạn bè được mô tả bởi im3l96; ngoại trừ không có tiền mã hóa của các khối.

nếu không có khoảng cách nào là hoàn toàn miễn phí, chúng ta phải chống phân mảnh. Đối với điều này, chúng tôi tìm thấy tín hiệu với các khe không được sử dụng nhiều nhất. Nếu các khoảng nhiều lần có cùng số lượng vị trí không được sử dụng, hãy chọn khoảng đầu tiên. Sau đó, chúng tôi tìm thấy tín hiệu lớn nhất trong khoảng này và gọi đệ quy cùng một thuật toán chèn cho tín hiệu nhỏ hơn (ngoại trừ đánh dấu khoảng thời gian chúng tôi đã chọn để chèn tín hiệu đầu tiên là không khả dụng bằng cách nào đó). Điều này di chuyển tín hiệu đến một nơi khác mà nó sẽ phù hợp. Sau đó chúng tôi tìm thấy tín hiệu nhỏ nhất tiếp theo trong khoảng thời gian đã chọn và thực hiện tương tự cho đến khi chúng tôi di chuyển tất cả các tín hiệu. Trường hợp xấu nhất của tín hiệu 2 ^ n-1 di chuyển; Trong đó N là số kích thước tín hiệu tiềm năng <= tín hiệu của chúng tôi (giả sử tín hiệu là bội số của 2 thì N = log2 (signalSize)).

Đây là một ví dụ. * là viết tắt của một vị trí được đánh dấu là không khả dụng khi chúng tôi gọi phương thức này một cách đệ quy (tức là khoảng thời gian mà phương thức gọi muốn đặt tín hiệu của nó và do đó không muốn cuộc gọi đệ quy cố gắng đặt tín hiệu vào)

Đây là một ví dụ đơn giản, đơn giản nhất mà tôi có thể đưa ra mà vẫn thể hiện sự phức tạp đầy đủ. Lưu ý: cấu trúc sau đây sẽ khó tạo, nhưng có thể là kết quả của sự chấp thuận của bạn bè nếu ai đó đã rất cố gắng.

FFFFFFFF__AA_B__EEEE_HGGCC_DII_J

Ai đó truyền tín hiệu Z cỡ 8

chúng tôi chọn bù 8:

defragInsert (z, cỡ 8)

effective structure: FFFFFFFF__AA_B__EEEE_HGGCC_DII_J

placing signal in interval: __AA_B__

defragInput (A, cỡ 2)

effective structure: FFFFFFFF********EEEE_HGGCC_DII_J
place signal in interval (offset 20)  _H

defragInput (H, size1)

effective structure: FFFFFFFF********EEEE**GGCC_DII_J
place signal between C & D

return defragInput (H, size1)

effective structure: FFFFFFFF********EEEE__GGCCHDII_J
place H at offset 20 now that it's open

return defragInput (A, size 2)

cấu trúc hiệu quả: FFFFFFFF_ _ _B__EEEEAAGGCCHDII_J di chuyển B ngay bây giờ ...

defragInput (B, size1)

cấu trúc hiệu quả: FFFFFFFF * ** * EEEEAAGGCCHDII_J đặt B giữa I & J

trả về defragInput (B, size1)

cấu trúc hiệu quả: FFFFFFFF_ __ _EEEEAAGGCCHDIIBJ thêm B

return defragInsert (z, size 8)

fianl structure: FFFFFFFFzzzzzzzzEEEEAAGGCCHDIIBJ

Thật khó để hiểu quá trình này đang làm gì. Bạn có thể cho chúng tôi và ví dụ về đầu vào (có thể với một đường ống có tín hiệu 8 hoặc 16 chứ không phải 255) và một ví dụ về đầu ra xấu và đầu ra tốt?
Neil

2
Tôi thứ 2 Neil, thật khó để hiểu cụ thể bạn đang hỏi gì. Nhưng có vẻ như bạn có thể đang cố gắng làm một cái gì đó giống như phân bổ bộ nhớ động. Trong thế giới nhúng, để giúp tránh sự phân mảnh, bộ nhớ động được phân chia thành các nhóm có kích cỡ khác nhau. I E. 10.000 khối đơn vị 256 byte. 1.000 khối đơn vị 1K, 200 khối đơn vị 1M, v.v. mới bị ghi đè. Sau đó, khi bộ nhớ động được yêu cầu, nó được lấy từ nhóm với các khối có kích thước nhỏ nhất có sẵn. Điều này dễ quản lý, nhanh chóng và tránh sự phân mảnh. Có thể làm việc cho bạn.
Dunk

Chỉnh sửa để thêm một minh họa trực quan của các đường ống. Vui lòng chấp nhận chỉnh sửa nếu bạn cảm thấy thích.
Bobson

Khi nào / cái gì quyết định việc thêm / loại bỏ tín hiệu?
Paddy3118

1
Tôi thứ 2 @Dunk, vấn đề tương tự như cấp phát bộ nhớ. Một phần của vấn đề trong ví dụ của bạn là nó phân bổ các vị trí theo cách khiến nó bị phân mảnh xấu (không sử dụng pool / chunk). Một giải pháp đơn giản mà tôi biết là sử dụng en.wikipedia.org/wiki/Buddy_memory_allocation . Sử dụng bạn thân, thay vì AAAA_CC_BBBB__DĐ bạn sẽ nhận được AAAACCDDBBBB__ (còn 4 chỗ trống). Không định vị lại, nó được phân bổ theo cách đó.
imel96

Câu trả lời:


4

Vấn đề tương tự như phân bổ bộ nhớ, vì vậy giải pháp đề xuất của tôi là sử dụng http://en.wikipedia.org/wiki/Buddy_memory_allocation . Sử dụng phân bổ bạn bè giảm thiểu sự phân mảnh xảy ra ở nơi đầu tiên bằng cách chọn không gian trống tiếp giáp nhỏ nhất trong đường ống cho tín hiệu.

Sử dụng ví dụ, đây là cách không gian sẽ được phân bổ cho kích thước ống 8:

Initial state
Pipe: ----------------

A (size 4), smallest available is 16, so split that into 2x4 and 1x8
Pipe: AAAA ---- --------

C (size of 2), smallest available is 4, split that into 2x2 
Pipe: AAAA CC -- --------

B (size of 4), smallest available is 8, split that into 2x4
Pipe: AAAA CC -- BBBB ----

D (size 2), smallest available is 2
Pipe: AAAA CC DD BBBB ----

Giải phóng không gian là vấn đề kiểm tra "bạn thân" của không gian được giải phóng; nếu bạn bè cũng rảnh rỗi, thì chúng có thể được hợp nhất để tạo thành không gian tiếp giáp lớn hơn. Vì vậy, nếu không gian được giải phóng theo thứ tự các tín hiệu đi vào, thì nó sẽ trông như thế này:

Free A (buddy of space being freed is not free)
Pipe: ---- CC DD BBBB ----

Free C (buddy is not free)
Pipe: ---- -- DD BBBB ----

Free B (buddy is free, merge)
Pipe: ---- -- DD --------

Free D (buddy is free, merge)
Pipe: ----------------

Nó cũng khá đơn giản và nhanh chóng vì chỉ có sự phân mảnh nhỏ, đặc biệt là vì kích thước của các tín hiệu là công suất bằng 2.

Nếu nó thực sự cần thiết thì việc chống phân mảnh / nén cũng có thể được thực hiện dễ dàng, đó chỉ là vấn đề tìm các khối được phân bổ có cùng kích thước với bạn bè tự do và hợp nhất chúng (di chuyển một khối được phân bổ sẽ tạo ra một khối miễn phí lớn hơn).


2

Chà, trước khi tìm kiếm một câu trả lời, trước tiên bạn nên xác định rõ ràng những gì bạn muốn giảm thiểu, đó là loại định vị tín hiệu nào được cho phép.

  • để lấy một (và chỉ một) tín hiệu ra khỏi đường ống và thêm tín hiệu này ở một nơi khác mà không có sự chồng chéo (và lặp lại bước đó n lần)?

  • hoặc để nhận n tín hiệu đồng thời từ đường ống của bạn và đặt lại chúng sau đó không có sự chồng chéo (được tính là n di chuyển)?

Rõ ràng, sự thay thế đầu tiên này bị hạn chế hơn nhiều, cho bạn không gian tìm kiếm nhỏ hơn nhiều. Ví dụ: để đi từ AAAA_CC_BBBB__DDđếnAAAA_CC___DDBBBB , người ta sẽ cần ít nhất 4 lần di chuyển nếu không cho phép tái định vị đồng thời và 2 lần di chuyển nếu được phép.

Tôi giả sử bạn có vấn đề đầu tiên trong đầu (vui lòng xác nhận điều đó), vì vậy đây là gợi ý của tôi cho việc này:

  • làm cho điều này một vấn đề tìm kiếm đồ thị. Đối với đường ống cho, mỗi cấu hình tín hiệu xác định một đỉnh của biểu đồ của bạn và các cạnh giữa các đỉnh đó là các vị trí có thể có.

  • cung cấp cho mỗi đỉnh một giá trị: độ dài của chuỗi khe liên tục dài nhất

Bây giờ, thật dễ dàng để sử dụng một kỹ thuật tìm kiếm đồ thị tiêu chuẩn như tìm kiếm đầu tiên theo chiều rộng hoặc tìm kiếm A * để tìm số bước nhỏ nhất cho đến khi bạn đạt được cấu hình đường ống có đủ không gian cho tín hiệu mới mà bạn muốn thêm.


Tôi có thể di chuyển nhiều tín hiệu như tôi muốn và thêm bao nhiêu tín hiệu tôi muốn, trên một đường ống nhất định. Vì vậy, miễn là kết quả cuối cùng không trùng lặp, mỗi lần di chuyển không cần phải đảm bảo không trùng lặp
DSollen

@dsollen: đây không phải là câu trả lời cho câu hỏi của tôi - Tôi không hỏi nếu n bị giới hạn. Tôi đã hỏi nếu di chuyển của bạn phải được thực hiện lần lượt, không có sự chồng chéo sau mỗi bước, hoặc nếu bạn có thể di chuyển hai tín hiệu cùng một lúc. Ví dụ: để chuyển đổi vị trí của hai tín hiệu, trường hợp đầu tiên cần ít nhất 3 lần di chuyển, trong khi trường hợp thứ hai chỉ cần 2.
Doc Brown

@dsollen: xem bản chỉnh sửa của tôi
Doc Brown

0

Bạn cần lấy một mẫu đại diện cho dữ liệu thực của bạn và mô phỏng các thuật toán đóng gói khác nhau. Hiện tại, tôi không có đủ thông tin để mô phỏng hệ thống nên không thể kiểm tra bất kỳ thuật toán nào hoạt động.


Có, tôi đồng ý, nhưng tôi không có bất kỳ dữ liệu nào về cách nó sẽ được sử dụng cho đến khi nó được phát hành và ra khỏi tay tôi. Tuy nhiên, thuật toán không cần phải được tối ưu hóa hoàn hảo cho một usecase cụ thể. Một thuật toán chung hoạt động khá tốt đối với mọi tín hiệu có khả năng sắp xếp ngẫu nhiên sẽ ổn. Một khái niệm như vậy có thể sẽ là trường hợp xấu nhất của N ^ 2, và điều đó thực sự có thể thực hiện được khi N quá nhỏ ... Tuy nhiên, tôi có thể gặp trường hợp xấu nhất là N ^ 2 nhưng trường hợp trung bình khá thì tốt hơn.
DSollen

Xin chào @dsollen, trong trường hợp đó tôi sẽ đưa nó ra khỏi cửa càng sớm càng tốt và nói với khách hàng rằng việc tối ưu hóa là có thể ngay khi bạn nhận được một số phản hồi. Nếu đó là một loại thì nó tương đương với việc đưa ra sắp xếp bong bóng hoặc sắp xếp hợp nhất vì bạn không có đủ thông tin để đề xuất Timsort.
Paddy3118

Cảm ơn vì bạn đã phản hồi. Đó thực chất là những gì tôi đã làm, phải mất rất lâu để đưa ra bất cứ điều gì tốt đẹp nên tôi đã làm nhanh nhất để thực hiện phê duyệt ngu ngốc cho bản phát hành này. Tuy nhiên, tôi khá chắc chắn rằng tôi sẽ sử dụng phiên bản con hoang lười biếng của phê duyệt phân bổ bạn bè được đề xuất bởi imel96 khi tôi phát hành tốt hơn. Thật khó để thu thập việc sử dụng vì nhiều trang web sẽ có các trường hợp sử dụng trung bình khác nhau. Và cuối cùng, một phê duyệt O (n) tối thiểu hóa nhu cầu chạy nó là rất nhanh, bất kỳ tối ưu hóa nào nữa sẽ không thể chấp nhận được đối với người dùng :)
DSollen

@dsollen: Chúc may mắn :-)
Paddy3118
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.