Tốc độ tăng trưởng lý tưởng cho một mảng được phân bổ động là bao nhiêu?


83

C ++ có std :: vector và Java có ArrayList, và nhiều ngôn ngữ khác có dạng mảng được cấp phát động riêng. Khi một mảng động hết dung lượng, nó sẽ được phân bổ lại thành một vùng lớn hơn và các giá trị cũ được sao chép vào mảng mới. Một câu hỏi trọng tâm đối với hiệu suất của một mảng như vậy là mảng phát triển kích thước nhanh như thế nào. Nếu bạn luôn chỉ phát triển đủ lớn để phù hợp với sức đẩy hiện tại, bạn sẽ luôn phải phân bổ lại. Vì vậy, điều hợp lý là tăng gấp đôi kích thước mảng hoặc nhân nó với 1,5x.

Có yếu tố tăng trưởng lý tưởng không? 2 x? 1,5 lần? Theo lý tưởng, ý tôi là được chứng minh về mặt toán học, cân bằng tốt nhất giữa hiệu suất và bộ nhớ bị lãng phí. Tôi nhận thấy điều đó về mặt lý thuyết, cho rằng ứng dụng của bạn có thể có bất kỳ phân phối tiềm năng nào của các lần đẩy mà điều này hơi phụ thuộc vào ứng dụng. Nhưng tôi tò mò muốn biết liệu có một giá trị "thường" tốt nhất hoặc được coi là tốt nhất trong một số ràng buộc nghiêm ngặt nào đó.

Tôi nghe nói có một tờ báo về điều này ở đâu đó, nhưng tôi không thể tìm thấy nó.

Câu trả lời:


43

Nó sẽ hoàn toàn phụ thuộc vào trường hợp sử dụng. Bạn có quan tâm nhiều hơn đến thời gian lãng phí khi sao chép dữ liệu xung quanh (và phân bổ lại các mảng) hay bộ nhớ thừa không? Mảng sẽ tồn tại trong bao lâu? Nếu nó sẽ không tồn tại được lâu, sử dụng một bộ đệm lớn hơn có thể là một ý kiến ​​hay - hình phạt chỉ tồn tại trong thời gian ngắn. Nếu nó cứ lởn vởn (ví dụ như trong Java, đi vào các thế hệ cũ hơn và cũ hơn) thì rõ ràng đó là một hình phạt.

Không có cái gọi là "yếu tố tăng trưởng lý tưởng". Nó không chỉ là về mặt lý thuyết ứng dụng phụ thuộc, đó là chắc chắn ứng dụng phụ thuộc.

2 là một yếu tố tăng trưởng khá phổ biến - tôi khá chắc chắn đó là những gì ArrayListList<T>trong .NET sử dụng. ArrayList<T>trong Java sử dụng 1.5.

CHỈNH SỬA: Như Erich đã chỉ ra, Dictionary<,>trong .NET sử dụng "nhân đôi kích thước rồi tăng lên số nguyên tố tiếp theo" để các giá trị băm có thể được phân phối hợp lý giữa các nhóm. (Tôi chắc rằng gần đây tôi đã xem tài liệu cho thấy rằng số nguyên tố thực sự không tuyệt vời để phân phối nhóm băm, nhưng đó là một đối số cho một câu trả lời khác.)


102

Tôi nhớ đã đọc nhiều năm trước tại sao 1,5 được ưu tiên hơn hai, ít nhất là khi áp dụng cho C ++ (điều này có thể không áp dụng cho các ngôn ngữ được quản lý, nơi hệ thống thời gian chạy có thể di chuyển các đối tượng theo ý muốn).

Lý do là:

  1. Giả sử bạn bắt đầu với phân bổ 16 byte.
  2. Khi bạn cần nhiều hơn, bạn phân bổ 32 byte, sau đó giải phóng 16 byte. Điều này để lại một lỗ hổng 16 byte trong bộ nhớ.
  3. Khi bạn cần thêm, bạn phân bổ 64 byte, giải phóng 32 byte. Điều này để lại một lỗ 48 byte (nếu 16 và 32 liền kề).
  4. Khi bạn cần thêm, bạn phân bổ 128 byte, giải phóng 64 byte. Điều này để lại một lỗ hổng 112 byte (giả sử tất cả các phân bổ trước đó là liền kề).
  5. Vân vân và vân vân.

Ý tưởng là, với sự mở rộng gấp 2 lần, không có thời điểm nào mà lỗ hổng thu được sẽ đủ lớn để sử dụng lại cho lần phân bổ tiếp theo. Sử dụng phân bổ 1,5x, thay vào đó chúng tôi có cái này:

  1. Bắt đầu với 16 byte.
  2. Khi bạn cần nhiều hơn, hãy phân bổ 24 byte, sau đó giải phóng 16 byte, để lại một lỗ 16 byte.
  3. Khi bạn cần thêm, hãy phân bổ 36 byte, sau đó giải phóng 24 byte, để lại lỗ 40 byte.
  4. Khi bạn cần thêm, hãy phân bổ 54 byte, sau đó giải phóng 36, để lại một lỗ 76 byte.
  5. Khi bạn cần nhiều hơn, hãy phân bổ 81 byte, sau đó giải phóng 54 byte, để lại một lỗ 130 byte.
  6. Khi bạn cần thêm, hãy sử dụng 122 byte (làm tròn lên) từ lỗ 130 byte.

5
Một bài đăng ngẫu nhiên trên diễn đàn mà tôi tìm thấy ( objectmix.com/c/… ) cũng có lý do tương tự. Một người đăng tuyên bố rằng (1 + sqrt (5)) / 2 là giới hạn trên để tái sử dụng.
Naaff

19
Nếu khẳng định đó là đúng, thì phi (== (1 + sqrt (5)) / 2) thực sự là con số tối ưu để sử dụng.
Chris Jester-Young

1
Tôi thích câu trả lời này vì nó tiết lộ sự hợp lý của 1,5x so với 2x, nhưng về mặt kỹ thuật của Jon là đúng nhất với cách tôi đã nêu. Tôi nên hỏi tại sao 1,5 đã được đề xuất trong quá khứ: p
Joseph Garvin

6
Facebook sử dụng 1.5 trong việc triển khai FBVector, bài viết ở đây giải thích tại sao 1.5 là tối ưu cho FBVector.
csharpfolk

2
@jackmott Đúng, chính xác như câu trả lời của tôi đã lưu ý: "điều này có thể không áp dụng cho các ngôn ngữ được quản lý, nơi hệ thống thời gian chạy có thể di chuyển các đối tượng theo ý muốn".
Chris Jester-Young

47

Lý tưởng nhất (trong giới hạn là n → ∞), đó là tỷ lệ vàng : ϕ = 1,618 ...

Trong thực tế, bạn muốn một cái gì đó gần giống như 1,5.

Lý do là bạn muốn có thể sử dụng lại các khối bộ nhớ cũ hơn, để tận dụng bộ nhớ đệm và tránh liên tục làm cho HĐH cung cấp cho bạn nhiều trang bộ nhớ hơn. Phương trình bạn sẽ giải để đảm bảo điều này rút gọn thành x n - 1 - 1 = x n + 1 - x n , có nghiệm tiếp cận x = ϕ với n lớn .


15

Một cách tiếp cận khi trả lời những câu hỏi như thế này là chỉ cần "ăn gian" và nhìn vào những gì các thư viện phổ biến làm, với giả định rằng một thư viện được sử dụng rộng rãi, ít nhất là không làm điều gì đó khủng khiếp.

Vì vậy, chỉ cần kiểm tra rất nhanh, Ruby (1.9.1-p129) dường như sử dụng 1.5x khi thêm vào một mảng và Python (2.6.2) sử dụng 1.125x cộng với một hằng số (in Objects/listobject.c):

/* This over-allocates proportional to the list size, making room
 * for additional growth.  The over-allocation is mild, but is
 * enough to give linear-time amortized behavior over a long
 * sequence of appends() in the presence of a poorly-performing
 * system realloc().
 * The growth pattern is:  0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
 */
new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);

/* check for integer overflow */
if (new_allocated > PY_SIZE_MAX - newsize) {
    PyErr_NoMemory();
    return -1;
} else {
    new_allocated += newsize;
}

newsizetrên là số phần tử trong mảng. Lưu ý rằng nó newsizeđược thêm vào new_allocated, vì vậy biểu thức với các bithifts và toán tử bậc ba thực sự chỉ là tính toán phân bổ quá mức.


Vì vậy, nó phát triển mảng từ n đến n + (n / 8 + (n <9? 3: 6)), có nghĩa là hệ số tăng trưởng, theo thuật ngữ của câu hỏi, là 1,25x (cộng với một hằng số).
ShreevatsaR

Nó sẽ không phải là 1,125x cộng với một hằng số?
Jason Creighton

10

Giả sử bạn tăng kích thước mảng lên x. Vì vậy, giả sử bạn bắt đầu với kích thước T. Lần tiếp theo bạn phát triển mảng, kích thước của nó sẽ là bao nhiêu T*x. Sau đó, nó sẽ được T*x^2và như vậy.

Nếu mục tiêu của bạn là có thể sử dụng lại bộ nhớ đã được tạo trước đó, thì bạn muốn đảm bảo bộ nhớ mới mà bạn cấp phát nhỏ hơn tổng bộ nhớ trước đó mà bạn đã phân bổ. Do đó, chúng ta có bất đẳng thức này:

T*x^n <= T + T*x + T*x^2 + ... + T*x^(n-2)

Chúng ta có thể loại bỏ T từ cả hai phía. Vì vậy, chúng tôi nhận được điều này:

x^n <= 1 + x + x^2 + ... + x^(n-2)

Một cách không chính thức, những gì chúng ta nói là lúc cấp phát nth, chúng ta muốn tất cả bộ nhớ đã được phân bổ trước đó của chúng ta lớn hơn hoặc bằng bộ nhớ cần ở lần cấp phát thứ n để chúng ta có thể sử dụng lại bộ nhớ đã được phân bổ trước đó.

Ví dụ: nếu chúng ta muốn có thể thực hiện việc này ở bước thứ 3 (tức là n=3), thì chúng ta có

x^3 <= 1 + x 

Phương trình này đúng với mọi x sao cho 0 < x <= 1.3(gần đúng)

Xem x chúng ta nhận được gì cho các n khác nhau dưới đây:

n  maximum-x (roughly)

3  1.3

4  1.4

5  1.53

6  1.57

7  1.59

22 1.61

Lưu ý rằng hệ số tăng trưởng phải nhỏ hơn 2kể từ đó x^n > x^(n-2) + ... + x^2 + x + 1 for all x>=2.


Dường như bạn tuyên bố rằng bạn đã có thể sử dụng lại bộ nhớ đã được phân bổ trước đó ở lần phân bổ thứ 2 với hệ số 1,5. Điều này không đúng (xem ở trên). Hãy cho tôi biết nếu tôi hiểu lầm bạn.
awx

Ở lần phân bổ thứ hai, bạn đang phân bổ 1,5 * 1,5 * T = 2,25 * T trong khi tổng số lần phân bổ bạn sẽ thực hiện cho đến lúc đó là T + 1,5 * T = 2,5 * T. Vậy 2,5 lớn hơn 2,25.
CEGRD

À, tôi nên đọc kỹ hơn; tất cả những gì bạn nói là tổng bộ nhớ được phân bổ theo thỏa thuận sẽ nhiều hơn bộ nhớ được cấp phát ở lần cấp phát thứ n, không phải là bạn có thể sử dụng lại nó ở lần cấp phát thứ n.
awx

4

Nó thực sự phụ thuộc. Một số người phân tích các trường hợp sử dụng phổ biến để tìm ra con số tối ưu.

Tôi đã thấy 1.5x 2.0x phi x và sức mạnh của 2 được sử dụng trước đây.


Phi! Đó là một con số đẹp để sử dụng. Tôi nên bắt đầu sử dụng nó từ bây giờ. Cảm ơn! +1
Chris Jester-Young

Tôi không hiểu ... tại sao lại phi? Nó có những đặc tính nào khiến nó phù hợp với việc này?
Jason Creighton

4
@Jason: phi tạo ra một chuỗi Fibonacci, vì vậy kích thước phân bổ tiếp theo là tổng của kích thước hiện tại và kích thước trước đó. Điều này cho phép tốc độ tăng trưởng vừa phải, nhanh hơn 1,5 nhưng không phải 2 (xem bài đăng của tôi tại sao> = 2 không phải là một ý kiến ​​hay, ít nhất là đối với các ngôn ngữ không được quản lý).
Chris Jester-Young

1
@Jason: Ngoài ra, theo một người bình luận cho bài đăng của tôi, bất kỳ số nào> phi trên thực tế đều là một ý tưởng tồi. Tôi đã không tự mình làm toán để xác nhận điều này, vì vậy hãy coi nó như muối bỏ bể.
Chris Jester-Young

2

Nếu bạn có phân phối theo độ dài mảng và bạn có một hàm tiện ích cho biết bạn muốn lãng phí không gian bao nhiêu so với lãng phí thời gian, thì bạn chắc chắn có thể chọn chiến lược thay đổi kích thước (và định kích thước ban đầu) tối ưu.

Lý do bội số đơn giản được sử dụng, rõ ràng là để mỗi phần phụ có thời gian không đổi được phân bổ. Nhưng điều đó không có nghĩa là bạn không thể sử dụng một tỷ lệ khác (lớn hơn) cho các kích thước nhỏ.

Trong Scala, bạn có thể ghi đè loadFactor cho các bảng băm thư viện tiêu chuẩn với một hàm xem kích thước hiện tại. Thật kỳ lạ, các mảng có thể thay đổi kích thước chỉ tăng gấp đôi, đó là điều mà hầu hết mọi người làm trong thực tế.

Tôi không biết về bất kỳ mảng nhân đôi (hoặc 1.5 * ing) nào thực sự thoát khỏi lỗi bộ nhớ và phát triển ít hơn trong trường hợp đó. Có vẻ như nếu bạn có một mảng lớn, bạn sẽ muốn làm điều đó.

Tôi muốn nói thêm rằng nếu bạn giữ các mảng có thể thay đổi kích thước đủ lâu và bạn ưu tiên không gian theo thời gian, thì việc phân bổ tổng thể đáng kể (đối với hầu hết các trường hợp) ban đầu và sau đó phân bổ lại cho chính xác kích thước khi bạn làm xong.


2

Hai xu khác

  • Hầu hết các máy tính đều có bộ nhớ ảo! Trong bộ nhớ vật lý, bạn có thể có các trang ngẫu nhiên ở khắp mọi nơi được hiển thị dưới dạng một không gian liền kề duy nhất trong bộ nhớ ảo của chương trình của bạn. Việc phân giải sự chuyển hướng được thực hiện bởi phần cứng. Cạn kiệt bộ nhớ ảo là một vấn đề trên các hệ thống 32 bit, nhưng nó thực sự không còn là vấn đề nữa. Vì vậy, việc lấp đầy lỗ không phải là mối quan tâm nữa (trừ những môi trường đặc biệt). Kể từ khi Windows 7 thậm chí Microsoft hỗ trợ 64 bit mà không cần nỗ lực thêm. @ 2011
  • O (1) đạt được với bất kỳ r > 1 hệ số nào. Chứng minh toán học tương tự hoạt động không chỉ cho 2 dưới dạng tham số.
  • r = 1,5 có thể được tính toán với old*3/2do đó không cần các phép toán dấu phẩy động. (Tôi nói /2vì các trình biên dịch sẽ thay thế nó bằng dịch chuyển bit trong mã hợp ngữ được tạo nếu họ thấy phù hợp.)
  • MSVC đã cho r = 1,5, vì vậy có ít nhất một trình biên dịch chính không sử dụng 2 làm tỷ lệ.

Như đã đề cập bởi ai đó 2 cảm thấy tốt hơn 8. Và 2 cảm thấy tốt hơn 1,1.

Cảm giác của tôi là 1,5 là một mặc định tốt. Ngoài ra nó còn phụ thuộc vào từng trường hợp cụ thể.


2
Sẽ tốt hơn nếu sử dụng n + n/2để trì hoãn việc tràn. Việc sử dụng n*3/2sẽ cắt giảm một nửa công suất có thể của bạn.
owacoder

@owacoder Đúng. Nhưng khi n * 3 không phù hợp nhưng n * 1,5 phù hợp thì chúng ta đang nói về rất nhiều bộ nhớ. Nếu n không có 32 bit thì n * 3 tràn khi n là 4G / 3, tức là khoảng 1.333G. Đó là một con số khổng lồ. Đó là rất nhiều bộ nhớ cần có trong một lần phân bổ. Tiết kiệm hơn nếu các phần tử không phải là 1 byte mà là 4 byte cho mỗi phần tử. Tự hỏi về trường hợp sử dụng ...
Notinlist

3
Đúng là nó có thể là một trường hợp cạnh, nhưng các trường hợp cạnh là những gì thường cắn. Tập thói quen tìm kiếm hiện tượng tràn hoặc các hành vi khác có thể gợi ý đến một thiết kế tốt hơn không bao giờ là một ý tưởng tồi, ngay cả khi nó có vẻ xa vời trong hiện tại. Lấy địa chỉ 32-bit làm ví dụ. Bây giờ chúng ta cần 64 ...
owacoder

1

Tôi đồng ý với Jon Skeet, ngay cả người bạn lý thuyết của tôi cũng khẳng định rằng điều này có thể được chứng minh là O (1) khi đặt hệ số thành 2x.

Tỷ lệ giữa thời gian cpu và bộ nhớ là khác nhau trên mỗi máy, và do đó, hệ số sẽ thay đổi nhiều. Nếu bạn có một máy tính có ram gigabyte và CPU chậm, việc sao chép các phần tử sang một mảng mới sẽ đắt hơn nhiều so với trên một máy nhanh, do đó có thể có ít bộ nhớ hơn. Đó là một câu hỏi có thể được trả lời trên lý thuyết, đối với một máy tính đồng nhất, điều này trong các tình huống thực tế không giúp được gì cho bạn cả.


2
Nói một cách chi tiết, việc tăng gấp đôi kích thước mảng có nghĩa là bạn nhận được các chèn O (1) được kích thích. Ý tưởng là mỗi khi bạn chèn một phần tử, bạn cũng sao chép một phần tử từ mảng cũ. Giả sử bạn có một mảng kích thước m , với m phần tử trong đó. Khi thêm phần tử m + 1 , không có khoảng trống, vì vậy bạn phân bổ một mảng mới có kích thước 2m . Thay vì sao chép tất cả m phần tử đầu tiên , bạn sao chép một phần tử mỗi khi bạn chèn một phần tử mới. Điều này giảm thiểu phương sai (tiết kiệm cho việc cấp phát bộ nhớ) và khi bạn đã chèn 2m phần tử, bạn sẽ sao chép tất cả các phần tử từ mảng cũ.
hvidgaard

-1

Tôi biết đó là một câu hỏi cũ, nhưng có một số điều mà mọi người dường như còn thiếu.

Đầu tiên, đây là phép nhân với 2: size << 1. Đây là phép nhân với bất kỳ thứ gì từ 1 đến 2: int (float (size) * x), trong đó x là số, * là dấu phẩy động toán học và bộ xử lý có để chạy các hướng dẫn bổ sung để truyền giữa float và int. Nói cách khác, ở cấp độ máy, việc nhân đôi chỉ cần một hướng dẫn duy nhất, rất nhanh để tìm ra kích thước mới. Nhân với một cái gì đó từ 1 đến 2 yêu cầu ít nhấtmột lệnh để truyền kích thước thành float, một lệnh để nhân (là phép nhân float, vì vậy có thể mất ít nhất gấp đôi số chu kỳ, nếu không phải là 4 hoặc thậm chí gấp 8 lần) và một lệnh để truyền trở lại int, và điều đó giả định rằng nền tảng của bạn có thể thực hiện phép toán float trên các thanh ghi mục đích chung, thay vì yêu cầu sử dụng các thanh ghi đặc biệt. Tóm lại, bạn nên kỳ vọng phép toán cho mỗi lần phân bổ mất ít nhất 10 lần thời gian dịch chuyển trái đơn giản. Tuy nhiên, nếu bạn đang sao chép nhiều dữ liệu trong quá trình phân bổ lại, điều này có thể không tạo ra nhiều khác biệt.

Thứ hai, và có lẽ là yếu tố thúc đẩy lớn: Mọi người dường như cho rằng bộ nhớ đang được giải phóng vừa tiếp giáp với chính nó, vừa tiếp giáp với bộ nhớ mới được cấp phát. Trừ khi bạn đang tự mình phân bổ trước tất cả bộ nhớ và sau đó sử dụng nó như một nhóm, thì điều này gần như chắc chắn không xảy ra. Hệ điều hành đôi khi có thểkết thúc việc này, nhưng hầu hết thời gian, sẽ có đủ sự phân mảnh không gian trống để bất kỳ hệ thống quản lý bộ nhớ tốt nào có thể tìm thấy một lỗ nhỏ nơi bộ nhớ của bạn sẽ vừa khít. Khi bạn thực sự nhận được các phần nhỏ, bạn có nhiều khả năng kết thúc với các phần liền kề, nhưng khi đó, phân bổ của bạn đủ lớn để bạn không thực hiện chúng thường xuyên, đủ để nó trở nên quan trọng nữa. Tóm lại, thật thú vị khi tưởng tượng rằng việc sử dụng một số lý tưởng sẽ cho phép sử dụng hiệu quả nhất dung lượng bộ nhớ trống, nhưng trên thực tế, điều đó sẽ không xảy ra trừ khi chương trình của bạn đang chạy trên kim loại trần (như trong, không có hệ điều hành bên dưới nó đưa ra tất cả các quyết định).

Câu trả lời của tôi cho câu hỏi? Không, không có con số lý tưởng. Nó là ứng dụng cụ thể đến nỗi không ai thực sự thử. Nếu mục tiêu của bạn là sử dụng bộ nhớ lý tưởng, thì bạn đã gặp khá nhiều may mắn. Đối với hiệu suất, phân bổ ít thường xuyên hơn sẽ tốt hơn, nhưng nếu chúng ta chỉ làm như vậy, chúng ta có thể nhân với 4 hoặc thậm chí 8! Tất nhiên, khi Firefox chuyển từ sử dụng 1GB lên 8GB chỉ trong một lần, mọi người sẽ phàn nàn, vì vậy điều đó thậm chí không có ý nghĩa. Dưới đây là một số quy tắc ngón tay cái mà tôi sẽ tuân theo:

Nếu bạn không thể tối ưu hóa việc sử dụng bộ nhớ, ít nhất đừng lãng phí các chu kỳ của bộ xử lý. Nhân với 2 nhanh hơn ít nhất là một bậc lớn hơn làm toán dấu phẩy động. Nó có thể không tạo ra sự khác biệt lớn, nhưng nó sẽ tạo ra sự khác biệt ít nhất (đặc biệt là ở giai đoạn đầu, trong thời gian phân bổ thường xuyên hơn và nhỏ hơn).

Đừng nghĩ quá nhiều. Nếu bạn chỉ dành 4 giờ để cố gắng tìm ra cách thực hiện một điều gì đó đã được thực hiện, bạn chỉ lãng phí thời gian của mình. Thành thật mà nói, nếu có một lựa chọn tốt hơn * 2, nó sẽ được thực hiện trong lớp vectơ C ++ (và nhiều nơi khác) nhiều thập kỷ trước.

Cuối cùng, nếu bạn thực sự muốn tối ưu hóa, đừng đổ mồ hôi cho những thứ nhỏ nhặt. Ngày nay, không ai quan tâm đến việc bộ nhớ 4KB bị lãng phí, trừ khi họ đang làm việc trên các hệ thống nhúng. Khi bạn nhận được 1GB đối tượng có dung lượng từ 1MB đến 10MB mỗi đối tượng, việc tăng gấp đôi có lẽ là quá nhiều (ý tôi là, tức là từ 100 đến 1.000 đối tượng). Nếu bạn có thể ước tính tỷ lệ mở rộng dự kiến, bạn có thể san bằng tỷ lệ tăng trưởng tuyến tính tại một thời điểm nhất định. Nếu bạn mong đợi khoảng 10 đối tượng mỗi phút, thì việc phát triển ở 5 đến 10 kích thước đối tượng mỗi bước (30 giây đến một phút một lần) có lẽ là tốt.

Tất cả những gì cần giải quyết là, đừng suy nghĩ quá nhiều, hãy tối ưu hóa những gì bạn có thể và tùy chỉnh cho ứng dụng (và nền tảng) của bạn nếu bạn phải.


11
Tất nhiên n + n >> 1là giống như 1.5 * n. Khá dễ dàng để đưa ra các thủ thuật tương tự cho mọi yếu tố tăng trưởng thực tế mà bạn có thể nghĩ đến.
Björn Lindqvist

đây là một quan điểm tốt. Tuy nhiên, lưu ý rằng bên ngoài ARM, điều này ít nhất tăng gấp đôi số lượng lệnh. (Nhiều lệnh ARM, bao gồm lệnh add, có thể thực hiện thay đổi tùy chọn trên một trong các đối số, cho phép ví dụ của bạn hoạt động trong một lệnh duy nhất. Mặc dù vậy, hầu hết các kiến ​​trúc không thể thực hiện điều này.) Không, trong hầu hết các trường hợp, nhân đôi số hướng dẫn từ một đến hai không phải là một vấn đề quan trọng, nhưng đối với các yếu tố tăng trưởng phức tạp hơn trong đó phép toán phức tạp hơn, nó có thể tạo ra sự khác biệt về hiệu suất cho một chương trình nhạy cảm.
Rybec Arethdar

@Rybec - Mặc dù có thể có một số chương trình nhạy cảm với các biến thể thời gian bởi một hoặc hai hướng dẫn, nhưng rất ít có khả năng bất kỳ chương trình nào sử dụng phân bổ lại động sẽ lo ngại điều đó. Nếu nó cần kiểm soát thời gian một cách tinh vi, nó có thể sẽ sử dụng bộ nhớ được phân bổ tĩnh để thay thế.
owacoder

Tôi chơi trò chơi, nơi một hoặc hai hướng dẫn có thể tạo ra sự khác biệt đáng kể về hiệu suất ở vị trí sai. Điều đó nói rằng, nếu việc phân bổ bộ nhớ được xử lý tốt, thì việc một vài hướng dẫn sẽ không xảy ra đủ thường xuyên để tạo ra sự khác biệt.
Rybec Arethdar
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.