2011-12-29 33 views
5

Tôi đang chạy một chương trình socket đa luồng với valgrind. Máy khách sẽ gửi yêu cầu tới máy chủ qua TCP, và sau đó bận chờ một boolean. Boolean sẽ được thiết lập khi hàm gọi lại phục vụ phản hồi từ máy chủ được gọi. Sau khi nhận được phản hồi (và cờ boolean được thiết lập), máy chủ sẽ gửi lại một yêu cầu và lặp lại thao tác này lặp lại trong một vòng lặp.valgrind quầy hàng trong chương trình socket đa luồng

Tôi nhận ra rằng truy cập không được quản lý đối với biến được chia sẻ (boolean) có thể gây ra sự cố luồng, nhưng tôi đã thử sử dụng mutexes pthread, và chương trình làm chậm khoảng 20% ​​(tốc độ là tầm quan trọng ở đây). Tôi tin rằng việc ghi vào biến boolean được chia sẻ là tốt vì nó có thể được thực hiện trong một chu kỳ đơn.

Chương trình chạy tốt bên ngoài valgrind, nhưng thường sẽ dừng khi chạy với valgrind. Tôi rời khỏi chương trình để chạy qua đêm .. thường mất một vài giây để hoàn thành, vì vậy tôi không nghĩ rằng đó là một trường hợp không chờ đợi đủ lâu để chương trình kết thúc. Luồng được quản lý bởi khung công cụ nguồn mở (sửa lỗi nhanh), vì vậy tôi không nghĩ rằng đó là vấn đề với cách tạo luồng/quản lý luồng.

Có ai biết về bất kỳ vấn đề nào với việc đo lường xung quanh các chương trình đa luồng/vòng lặp chờ đợi bận/liên lạc ổ cắm (hoặc kết hợp các kết nối này) không?

+1

bận chờ đợi trên biến boolean chia sẻ không được thực hiện trong một chu kỳ đơn, nó được thực hiện trong một vài chu kỳ trên mỗi vòng lặp và nếu vòng lặp bận của bạn đang đợi trên một chuyến đi vòng qua mạng TCP, thì vòng lặp có khả năng sẽ lặp lại vài tỷ lần (và do đó lãng phí vài tỷ chu kỳ CPU có thể được sử dụng tốt hơn ở nơi khác). Một giải pháp tốt hơn so với một trong những điều bạn đã đề cập là chờ một biến điều kiện và có chức năng gọi lại báo hiệu biến điều kiện để đánh thức luồng của bạn khi dữ liệu sẵn sàng. –

+0

Tôi đã nói rằng việc ghi vào biến boolean được thực hiện trong một chu kỳ đơn (không phải toàn bộ quá trình đợi bận). Có nói rằng tôi nên nói rằng việc ghi vào biến boolean được thực hiện một cách nguyên tử (như bộ nhớ cache bị xóa vv có thể đẩy một ghi một byte đơn qua một chu kỳ CPU đơn) – Taras

+0

Điều Jeremy nói - chờ đợi bận là một ý tưởng tồi, biến điều kiện là tốt hơn, và không thể chậm hơn ... – BillT

Trả lời

6

Trong khi các câu trả lời khác tập trung vào việc nhấn mạnh rằng bạn sử dụng phương pháp đồng bộ hóa chuẩn (điều tôi hoàn toàn đồng ý), tôi nghĩ thay vào đó tôi nên trả lời câu hỏi của bạn về Valgrind.

Theo như tôi biết không có vấn đề gì với Valgrind đang chạy trong môi trường nhiều luồng. Tôi tin rằng Valgrind buộc ứng dụng chạy trên một lõi đơn lẻ, nhưng khác với việc nó không ảnh hưởng đến chủ đề của bạn.

Điều Valgrind có thể làm cho ứng dụng của bạn là thay đổi thời gian và tương tác giữa các chuỗi của bạn theo cách có thể làm lộ các lỗi và điều kiện chủng tộc trong mã mà bạn không thường thấy khi chạy độc lập.

Cùng một logic bạn đã áp dụng để quyết định rằng lỗi không thể nằm trong khung luồng nguồn mở mà bạn đang sử dụng cũng áp dụng cho Valgrind theo ý kiến ​​của tôi. Tôi khuyên bạn nên xem xét những lỗi này là lỗi trong mã của bạn và gỡ lỗi chúng như vậy, bởi vì đó là khả năng nhất của chúng.

Một lưu ý phụ, sử dụng mutex có thể là quá mức cần thiết cho sự cố bạn đã mô tả. Bạn nên điều tra các semaphores hoặc biến điều kiện để thay thế.

Chúc may mắn.

+0

Không hoàn toàn bị thuyết phục rằng có lỗi trong mã của tôi, nhưng bài đăng của bạn được ghi nhận. Lưu ý phụ - Tôi đã xem xét các biến điều kiện sử dụng thư viện pthread, và những yêu cầu này đòi hỏi một mutex để ngăn chặn điều kiện chủng tộc trên chính điều kiện thực tế. – Taras

+1

@Taras: chính xác trên biến điều kiện. Semaphores sẽ là sở thích của tôi trong trường hợp này. Nhẹ hơn nhiều so với mutex. Về vấn đề treo, tại sao bạn không kiểm tra quá trình treo với gdb để tìm hiểu nó đang làm gì? – Miguel

3

Đọc/ghi boolean không phải là thao tác nguyên tử trên x86.

Xem câu hỏi của tôi ở đây: Is volatile a proper way to make a single byte atomic in C/C++?

+0

Câu trả lời cho biết rằng hầu hết việc viết boolean là nguyên tử: "CPU thường đọc và ghi các byte đơn nguyên tử". Từ câu trả lời của câu hỏi, vấn đề không phải là nguyên tử, đó là thời điểm tất cả các CPU nhìn thấy giá trị mới. – Taras

2

Ngay cả khi viết boolean của bạn là một hoạt động nguyên tử, các compiler and the CPU are free to re-order the update xung quanh bộ nhớ khác truy cập. Chuỗi bận chờ đợi của bạn có thể thức từ vòng lặp bận và phát hiện ra rằng cấu trúc dữ liệu được chia sẻ có chưa thực sự được cập nhật.

Tôi khuyên bạn nên gắn bó với các nguyên thủy thô sẵn có để bạn viết nhất quán chương trình thực thi chính xác như bạn muốn, mỗi lần.

+0

Điều duy nhất được chia sẻ giữa hai luồng là cờ boolean (nó đang được sử dụng như một tín hiệu). Chủ đề chờ đợi bận sẽ chỉ tỉnh dậy nếu cờ đã được thiết lập, điều đó có nghĩa là thay đổi trong cờ phải được truyền đến CPU đang chạy chuỗi chờ bận. Cho điều này, sẽ mã như mô tả vẫn không hoạt động chính xác? – Taras

+0

Heh, bạn có _tried_ tín hiệu chưa? Điều đó có thể làm các trick. :) – sarnold

Các vấn đề liên quan