Khi nào thì sử dụng Mảng song song?


14

Tôi đã chạy vào mã (mã mới) sử dụng cái mà tôi gọi là 'Mảng song song' hoặc Danh sách. Có nghĩa là có 2 mảng chứa dữ liệu liên quan và được liên kết bởi vị trí (chỉ mục) của chúng trong mảng.

Tôi xem xét điều này khó hiểu và dễ bị lỗi. Giải pháp tôi thường đề xuất là tạo một đối tượng được gọi Companyvới các trường CompanyId và CompanyName.

Một ví dụ rất thực tế:

List<string> companyNames;
List<int> companyIds;

//...They get populated somewhere and we then process

for(var i=0; i<companyNames.Count; i++)
{
    UpdateCompanyName(companyIds[i],companyNames[i]);
}

Là những mảng song song được coi là thực hành xấu ?


9
Đơn giản chỉ cần chứng minh thêm rằng không có ngôn ngữ nào được phát minh trong đó bạn không thể viết Fortran.
andy xoài

3
Có thể có những lợi ích bộ nhớ đệm (khá đáng kể) để làm một cái gì đó như thế này (mặc dù bạn cần các mảng liền kề không có danh sách liên kết) và điều này đã trở nên hơi phổ biến trong lập trình trò chơi liên quan đến "thiết kế hướng dữ liệu". Tuy nhiên, điều này dường như không áp dụng cho trường hợp của bạn. Nó không giống như bạn đang thực hiện mã quan trọng hiệu suất.
Derek Elkins rời SE

2
@DerekElkins ... Thật thú vị khi nhận xét của bạn sau khi so sánh điều này với mã Fortran. Các phiên bản ban đầu của Fortran thiếu hỗ trợ cho các cấu trúc do người dùng xác định và ngay cả sau khi được thêm vào, mã Fortran thành ngữ sử dụng nhiều mảng thuộc tính chứ không phải mảng cấu trúc. Và điều này thường được ghi nhận là một phần lý do Fortran thường được coi là ngôn ngữ nhanh nhất.
Jules

3
Một ý nghĩ tiếp tuyến cho câu hỏi này: nhiều ngôn ngữ chức năng tích cực khuyến khích làm việc với các danh sách như vậy. Chúng có một chức năng, thường được gọi là zip, chuyển đổi chúng thành một danh sách các bộ dữ liệu. Mã của bạn trông giống như C #. Phiên bản mới nhất của C # đã thêm hỗ trợ cho các bộ dữ liệu hạng nhất. Tôi tự hỏi nếu, do đó, họ đã thêm một chức năng zip ở đâu đó có thể đưa danh sách của bạn vào một cấu trúc hữu ích cho bạn một cách tự động?
Jules

4
Vâng, đôi khi có những lý do để sử dụng hai mảng một cách có chủ ý, nhưng trong 99% tất cả các trường hợp tôi đã thấy điều này, lý do duy nhất cho nó là sự lười biếng của tác giả ban đầu để giới thiệu một cấu trúc dữ liệu ôm ấp.
Doc Brown

Câu trả lời:


23

Dưới đây là một số lý do tại sao một người nào đó có thể sử dụng mảng parrel:

  1. Trong một ngôn ngữ không hỗ trợ các lớp hoặc cấu trúc
  2. Để tránh khóa luồng khi các luồng riêng lẻ chỉ sửa đổi một trong các cột
  3. Khi phương pháp kiên trì buộc những thứ này được lưu trữ riêng và bạn đang khôi phục chúng.
  4. Chúng có thể tiêu thụ ít bộ nhớ hơn nếu các cấu trúc được đệm. (không áp dụng cho các loại dữ liệu này trong C #)
  5. Khi các phần của dữ liệu cần được giữ sát nhau để sử dụng hiệu quả bộ đệm CPU (sẽ không có ích trong đoạn mã trên).
  6. Sử dụng mã op Hướng dẫn nhiều dữ liệu (SIMD). (không áp dụng cho mã này hoặc chuỗi nào cả)

Tôi không thấy bất kỳ lý do thuyết phục nào để làm điều này trong trường hợp này ... và có khả năng có nhiều lựa chọn tốt hơn trong tất cả các điều trên hoặc không hữu ích trong ngôn ngữ cấp cao.


3
Chúng có thể tiêu thụ ít bộ nhớ hơn nếu các cấu trúc được đệm. Một số mảng lớn, được phân bổ thông minh, có thể tiêu thụ ít bộ nhớ hơn một mảng cấu trúc.
Frank Hileman

4
4. Khi các phần của dữ liệu cần được giữ sát nhau để sử dụng hiệu quả bộ đệm CPU. (Cần thiết trong những trường hợp hiếm hoi.)
Blrfl

@Frank Hileman, Whilie Tôi nghĩ rằng câu trả lời của TheCatWhisperer là hoàn toàn chính xác, thực sự nhận xét của bạn là lý do tốt nhất để chọn phương pháp này. Nếu mức tiêu thụ bộ nhớ là rất quan trọng, chi phí bộ nhớ trên phần đệm cấu trúc có thể là đáng kể, đặc biệt là nếu số lượng lớn đang hoạt động.
Vladimir Stokic

Đã thêm đề xuất của bạn vào câu trả lời
TheCatWhisperer

Re (2), thế nào? Tôi có thể viết một chương trình với một mảng cấu trúc và khóa trên mỗi trường dễ dàng như tôi có thể viết một chương trình với nhiều mảng và khóa trên mỗi mảng.
Solomon chậm

7

Tôi đã phạm tội khi sử dụng các mảng song song . Đôi khi bạn đi vào cấu trúc rất nhiều, bạn không muốn nghĩ về cách trừu tượng hóa nó. Trừu tượng hóa có thể khó hơn một chút để tái cấu trúc vì vậy bạn không muốn khởi động ngay vào nó cho đến khi bạn chứng minh được những gì bạn thực sự cần.

Tại thời điểm đó, mặc dù nó đáng để xem xét tái cấu trúc để trừu tượng hóa các chi tiết. Thường thì lý do lớn nhất khiến tôi không muốn làm điều đó hóa ra là thật khó để nghĩ ra một cái tên hay.

Nếu bạn có thể thấy một cách tốt để các mảng song song trừu tượng đi làm điều đó mỗi lần. Nhưng đừng làm tê liệt bản thân bằng cách từ chối chạm vào chúng. Đôi khi một chút mã bẩn là bước đệm tốt nhất để mã tuyệt vời.


6

Mẫu này đôi khi cũng được gọi là Cấu trúc của mảng (trái ngược với Mảng cấu trúc) và cực kỳ hữu ích khi mã hóa vectơ. Thay vì viết một phép tính chạy trên một cấu trúc đơn lẻ và vectơ bit của nó, bạn viết phép tính như bình thường, ngoại trừ với nội tại SSE để nó chạy trên 4 cấu trúc thay vì một cấu trúc. Điều này thường dễ dàng hơn, và hầu như luôn luôn nhanh hơn. Định dạng SoA làm cho điều này rất tự nhiên. Nó cũng cải thiện sự liên kết, giúp cho bộ nhớ SSE hoạt động nhanh hơn.


Có, phương pháp này được sử dụng khi học máy trên GPU. Đó là thông lệ để tách các trường của nhiều ví dụ riêng biệt, đóng gói tất cả các giá trị của từng trường vào một tenxơ riêng biệt và chuyển các tenxơ đó để được tính toán hàng loạt để đưa ra một danh sách dự đoán.
Phục hồi Monica
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.