2012-07-02 13 views
32

Trong khi nhìn vào trạng thái thực hiện Clang và g ++ C++ 11, tôi nhận thấy một điều lạ:
chúng hỗ trợ nguyên tử C++ 11, nhưng họ không hỗ trợ mô hình bộ nhớ C++ 11.
Tôi đã bị ấn tượng rằng bạn phải có mô hình bộ nhớ C++ 11 để sử dụng nguyên tử. Vậy chính xác sự khác nhau giữa hỗ trợ cho mô hình nguyên tử và bộ nhớ là gì?
Việc thiếu hỗ trợ mô hình bộ nhớ có nghĩa là các chương trình C++ 11 hợp pháp sử dụng std::atomic<T> arent seq nhất quán không?Làm thế nào các trình biên dịch C++ có thể hỗ trợ C++ 11 nguyên tử, nhưng không hỗ trợ mô hình bộ nhớ C++ 11

tham khảo:
http://clang.llvm.org/cxx_status.html
http://gcc.gnu.org/gcc-4.7/cxx0x_status.html

+0

Tính nguyên tử là một trong (ba?) Thuộc tính của mô hình bộ nhớ, cùng với khả năng hiển thị bộ nhớ và thứ tự bộ nhớ. Nguyên tử không phải là một 'từ đồng nghĩa' của mô hình bộ nhớ. – mloskot

Trả lời

15

Một trong những vấn đề là định nghĩa "vị trí bộ nhớ", cho phép (và buộc trình biên dịch hỗ trợ) khóa các thành viên cấu trúc khác nhau bằng các khóa khác nhau. Có một số discussion about a RL problem caused by this.

Về cơ bản vấn đề là có một struct định nghĩa như thế này:

struct x { 
    long a; 
    unsigned int b1; 
    unsigned int b2:1; 
}; 

trình biên dịch là miễn phí để thực hiện bằng văn bản cho b2 bằng cách ghi đè b1 quá (và rõ ràng, đánh giá từ báo cáo, nó). Do đó, hai trường phải được khóa là một. Tuy nhiên, do kết quả của mô hình bộ nhớ C++ 11, điều này bị cấm (tốt, không thực sự bị cấm, nhưng trình biên dịch phải đảm bảo các bản cập nhật đồng thời cho b1b2 không can thiệp, nó có thể làm điều đó bằng cách khóa hoặc CAS-ing mỗi cập nhật như vậy, tốt, cuộc sống là khó khăn trên một số kiến ​​trúc). Trích dẫn từ báo cáo:

Tôi đã đưa ra vấn đề với kẻ GCC của chúng tôi và họ nói với tôi rằng: "C không không cung cấp sự bảo đảm như vậy, cũng không thể đáng tin cậy khóa khác nhau lĩnh vực cấu trúc với ổ khóa khác nhau nếu họ chia sẻ tự nhiên vùng nhớ kích thước từ tự nhiên. Mô hình bộ nhớ C++ 11 sẽ đảm bảo điều này, nhưng điều đó không được triển khai cũng như bạn không xây dựng hạt nhân bằng trình biên dịch C++ 11 . "

Thông tin thú vị cũng có thể được tìm thấy trong số wiki.

+0

để kỹ thuật cho tôi, nhưng đây là thông tin tốt đẹp: Lý do chúng tôi đề cập đến mô hình bộ nhớ C11/C++ 11 là vì chúng tôi dự định hỗ trợ , có khả năng cho GCC 4.8, khi được yêu cầu bởi một số tùy chọn (hoặc theo mặc định khi chọn những tiêu chuẩn đó ?, hoặc khi được yêu cầu một cách rõ ràng).Điều này sẽ thậm chí vô hiệu hóa một số tối ưu hóa tốt cho các ứng dụng đơn luồng, nhưng không tốt trong các mô hình bộ nhớ đó, không được sử dụng trong OpenMP hoặc cho nhiều chương trình được tạo luồng khác . Ví dụ. chuyển động lưu trữ vòng lặp nếu nó không được đảm bảo biến số luôn được lưu trong vòng lặp: – NoSenseEtAl

+0

int x; void foo (int j) { int i; cho (i = 0; i <100000; i ++) nếu (i> j) x = i; } không thể thực hiện được, vì nếu không nó sẽ giới thiệu một tmp = x; ... x = tmp; vào mã mà nếu không sẽ chạm vào biến, vì vậy nếu một số khác ... khác chủ đề sửa đổi x, nó có thể có giá trị không mong muốn. \t Jakub – NoSenseEtAl

+0

chỉnh sửa tuyệt vời (liên kết thật tuyệt vời, thường tôi tự hỏi đâu là nơi làm những điều kỳ diệu (trình biên dịch)) và tại sao họ ngại ngùng về chia sẻ thông tin. :) thực tế là hầu hết các thông tin thời gian là có, nhưng không dễ dàng googlable :) – NoSenseEtAl

0

Nó không đến nỗi họ không hỗ trợ mô hình bộ nhớ, nhưng mà họ không (chưa) hỗ trợ các API trong tiêu chuẩn để tương tác với bộ nhớ mô hình. API đó bao gồm một số mutexes.

Tuy nhiên, cả Clang và GCC đều là chủ đề nhận thức được càng tốt mà không có tiêu chuẩn chính thức trong một thời gian. Bạn không phải lo lắng về việc tối ưu hóa di chuyển mọi thứ sang bên trái của các hoạt động nguyên tử.

+1

Câu trả lời đó thực sự không đạt yêu cầu; danh sách các tính năng được liên kết trong câu hỏi * cụ thể * nói về mô hình bộ nhớ (và đề xuất của nó), không phải bất kỳ API, thư viện, mutexes và whatnot. Hơn nữa, ít nhất gcc 4,7 * không * có các mutex trong thư viện. Nói chuyện như "là chủ đề nhận thức càng tốt mà không có một tiêu chuẩn chính thức" chỉ là nhảm nhí; nó không có nghĩa gì cả. Chủ đề nhận thức cho bạn biết không có gì về những gì trình biên dịch làm và có chắc chắn nhiều hơn để nó hơn "di chuyển những thứ đến bên sai của hoạt động nguyên tử". – jpalecek

+1

@jpalecek trong khi tôi đồng ý rằng câu trả lời không phải là tuyệt vời mà không cần phải nói bs. :) Và yeah mutexes là trong g + + từ 4,6 ít nhất, mặc dù nếu tôi nhớ chính xác atomic_thread_fence wasnt. :) Không thể kiểm tra ngay bây giờ, (Im trên VS atm). – NoSenseEtAl

+0

@NoSenseEtAl: atomic_thread_fence nằm trong gcc-4.7. Tôi đã sử dụng thuật ngữ BS để chỉ các cụm từ tiếp thị mơ hồ, như "hỗ trợ bản địa cho ...", điều đó có vẻ quan trọng, nhưng sau một chút suy nghĩ, chúng không có ý nghĩa gì cả. – jpalecek

11

Tôi đoán "Thiếu mô hình bộ nhớ" trong các trường hợp này chỉ có nghĩa là trình tối ưu hóa được viết trước khi mô hình bộ nhớ C++ 11 được xuất bản và có thể thực hiện tối ưu hóa không hợp lệ. Rất khó khăn và tốn thời gian để xác thực tối ưu hóa mô hình bộ nhớ, do đó, không có gì ngạc nhiên khi các đội clang/gcc chưa hoàn thành.

Việc thiếu hỗ trợ mô hình bộ nhớ có nghĩa là các chương trình C++ 11 hợp pháp sử dụng std :: seent arent seq nhất quán không?

Vâng, đó là một khả năng. Nó thậm chí còn tồi tệ hơn: trình biên dịch có thể giới thiệu các cuộc đua dữ liệu vào (theo tiêu chuẩn C++ 11) các chương trình không có chủng tộc, ví dụ: bằng cách giới thiệu đầu cơ viết.

Ví dụ, một số trình biên dịch C++ sử dụng để thực hiện tối ưu hóa này:

for (p = q; p = p -> next; ++p) { 
    if (p -> data > 0) ++count; 
} 

thể được tối ưu hóa thành:

register int r1 = count; 
for (p = q; p = p -> next; ++p) { 
    if (p -> data > 0) ++r1; 
} 
count = r1; 

Nếu tất cả p->data là không âm, mã nguồn gốc không viết đến count, nhưng mã được tối ưu hóa. Điều này có thể giới thiệu một cuộc đua dữ liệu trong một chương trình không có chủng tộc khác, vì vậy đặc tả C++ 11 không cho phép tối ưu hóa như vậy. Các trình biên dịch hiện tại phải xác minh (và điều chỉnh nếu cần thiết) tất cả các tối ưu hóa.

Xem Concurrency memory model compiler consequences để biết chi tiết.

+0

u biết những gì là buồn cười? MS nói cho VC++ 11: Mô hình bộ nhớ: N2429 làm cho ngôn ngữ lõi nhận ra sự tồn tại của đa luồng, nhưng dường như không có gì để thực hiện trình biên dịch làm (ít nhất, một đã hỗ trợ đa luồng). Vì vậy, nó là N/A trong bảng. – NoSenseEtAl

+0

@NoSenseEtAl: Đó chỉ là một phần rất cụ thể của toàn bộ mô hình bộ nhớ. Cùng một bảng cũng có "thứ tự phụ thuộc dữ liệu" (N2664) đã yêu cầu công việc. Thông thường, chúng tôi cũng tính rằng đó là một phần của mô hình bộ nhớ C++ 11. – MSalters

+0

Ok .. vì vậy họ lười biếng. Đó là những gì tôi nghĩ. –