8

nghệ stack: C#/NET 4/WinFormschiến lược để làm việc với một lượng lớn dữ liệu hình ảnh

Bối cảnh:

Dự án mà tôi đang làm việc là một ứng dụng trực quan cho một loạt các ngăn xếp hình ảnh. Cụ thể, mỗi chồng hình ảnh được căn chỉnh với lưới, hiển thị cùng một hình ảnh cùng một lúc và các chức năng xử lý được áp dụng cho các hình ảnh hiện đang xem. Các hình ảnh ngăn xếp chính họ là 150-300 MB và mỗi hình ảnh là 512KB-1MB. Một tập dữ liệu điển hình sẽ bao gồm ~ 100 ngăn xếp hình ảnh.

Câu hỏi:

Để thử và làm việc với lượng dữ liệu này, tôi đang sử dụng một vài technqiues:

  • bộ nhớ ánh xạ tập tin: ngăn xếp hình ảnh được nạp từ đĩa vào khởi động ứng dụng
  • biên soạn dưới x64 với mã không an toàn được cho phép: Rõ ràng là tôi cần không gian địa chỉ 64 bit cho các tệp có kích thước này. Tôi đang di chuyển hình ảnh hiện được hiển thị từ tệp ánh xạ bộ nhớ sang phương thức tạo bitmap qua Marshal.Copy với các con trỏ không an toàn.
  • System.Threading.Tasks: Tôi đang sử dụng các vòng lặp song song để xử lý nếu có thể
  • System.Drawing.BufferedGraphicsContext: Mỗi ngăn xếp hình ảnh có một hình ảnh hoạt động được tổng hợp thành BufferedGraphicsContext trước khi được chuyển đến PictureBox để hiển thị người dùng.
  • yêu cầu hệ thống cao cấp: quad-core CPU hoặc tốt hơn, SSD, bộ nhớ 12GB, vv

Tuy nhiên, thậm chí sử dụng tất cả những điều trên, các reponsiveness nhiều lá để được mong muốn. Sử dụng SysInternals Process Explorer, mức sử dụng CPU thấp (< 25%) trong khi mức sử dụng bộ nhớ tăng lên mức giới hạn trước khi việc thu gom rác xảy ra.

Hồ sơ cho thấy rằng hầu hết thời gian thực hiện được dành để lấy dữ liệu ra khỏi tệp ánh xạ bộ nhớ. Tôi giả sử nó chờ đợi khi các trang hệ điều hành bộ nhớ yêu cầu trở lại vào bộ nhớ hoạt động?

Tôi có thể làm gì khác để cải thiện hiệu suất?

Lưu ý:

  • Hầu hết, nếu không phải tất cả, ngăn xếp hình ảnh sẽ có thể xem cùng lúc nên cắt cho khung nhìn hiện tại có thể không mang lại nhiều tốc độ.
  • Thay đổi kích thước để hiển thị là một tùy chọn, nhưng dữ liệu gốc hoàn chỉnh phải luôn sẵn sàng để xử lý vì vậy có vẻ như đó chỉ là một bước bổ sung.

Cập nhật 1:

  • Đối với bộ nhớ, hộp phát triển của tôi chỉ có 6 GB (và tôi đang cố gắng để tải các tập tin ít như vậy), nhưng hệ thống triển khai sẽ có 24 GB .
  • Tôi đang xem xét việc sử dụng tối ưu hóa SSE thông qua Intel Performance Primitives và GPU accelleration thông qua CUDA.
  • Lý do tôi đang cố gắng tải tất cả dữ liệu vào bộ nhớ là vì một bước quan sát trực quan quan trọng là đi qua các ngăn xếp hình ảnh ở 15-60 Hz và tôi sợ bị đập.
+0

chỉ muốn kiểm tra - không có cách nào mà rất nhiều điều này chỉ có thể được trao cho một card đồ họa để lo lắng về? –

+0

"rất nhiều bộ nhớ" là gì cho bạn? –

Trả lời

5

Trước hết, tôi nghĩ rằng việc sử dụng mã không an toàn và các tệp ánh xạ bộ nhớ không phải là rất hữu ích. Bạn cần đọc khoảng 20GB dữ liệu từ đĩa. Đọc nó từ đĩa sẽ mất nhiều thời gian hơn một bản sao phụ trong bộ nhớ trong trường hợp bạn chỉ sử dụng các luồng - bạn đã tối ưu hóa ở vị trí sai.

Tôi nghĩ bạn nên nhìn nó từ một góc độ khác. Bạn đang hiển thị các chồng hình ảnh - giá trị 20 GB trên màn hình có thể hiển thị dưới 10MB dữ liệu. Bạn không cần phải đọc 20GB dữ liệu để hiển thị tất cả các ngăn xếp hình ảnh và cung cấp giao diện người dùng đáp ứng trong khi xử lý những hình ảnh này. Bạn chỉ cần tải hình ảnh hàng đầu từ mỗi ngăn xếp - sẽ nhiều hơn nhiều hơn nhanh hơn.

Đối với việc xử lý thực tế, trừ khi bạn có thể sử dụng GPU bằng cách nào đó, tôi không nghĩ rằng bạn có thể làm cho nó nhanh hơn xử lý hình ảnh song song. Tôi đoán nó phụ thuộc vào việc xử lý bạn thực sự làm.

0

Ngược lại như vậy, bạn nên thử chạm vào (nghĩa là đọc một byte ở mọi bội số của 4KB từ đầu mỗi tệp) tất cả dữ liệu trong tệp ánh xạ bộ nhớ khi ứng dụng của bạn khởi động. Vì bạn có đủ RAM, vấn đề có thể không phải là hệ điều hành đang phân trang hình ảnh của bạn, nhưng nó không phải lúc đầu phân trang chúng. Các tệp ánh xạ bộ nhớ được tải một cách lười biếng, vì vậy hệ điều hành sẽ không nhấn đĩa cho đến khi bạn thực sự cố gắng truy cập dữ liệu trong các tập tin được ánh xạ bộ nhớ. Kết quả là, việc chạm vào bộ nhớ khi tải ứng dụng sẽ khiến đĩa đọc xảy ra sau đó thay vì thời gian người dùng nhìn vào ngăn xếp hình ảnh.

0

Giảm số lượng hình ảnh được xử lý song song để tăng vị trí bộ nhớ. Vì vậy, 4 lõi của bạn sẽ xử lý một hình ảnh cùng một lúc. Điều này rất tốt cho bộ nhớ cache của bộ xử lý.

2

Bạn vẫn có thể tạo hình ảnh ngón tay cái được tạo trước cho mỗi hình ảnh và chỉ tải chúng trên Grid khi tất cả hình ảnh có sẵn. Trong thời điểm người dùng sẽ áp dụng hiệu ứng/chuyển đổi cho hình ảnh, bạn chỉ có thể tải chỉ hình ảnh đó. Và ngay cả trong khi tải chỉ hình ảnh đó bạn có thể chia nó ra để cắt các phần tải và tải chúng theo cách không đồng bộ. Nếu bạn nhìn vào Google Street View, cách tải, sau khi phóng to, bạn sẽ tìm ra rằng không bao giờ là toàn bộ hình ảnh (ngay cả khi bạn được yêu cầu) tải ngay lập tức, nhưng nó được tải theo từng khu vực.

Một công nghệ rất thú vị khác mà tôi nghĩ, Deep Zoom có thể, nếu không phải là câu trả lời cho các vấn đề của bạn, nhưng ít nhất có thể cung cấp gợi ý tốt.

Another example on Deep Zoom từ Scott Hanselman

Chúc may mắn.

0

Tùy thuộc vào độ lớn của màn hình và hình ảnh, bạn có thể thử lấy mẫu hình ảnh xuống để vừa với độ phân giải của ô vuông. Sau đó, nếu bạn muốn tập trung vào một số điểm của hình ảnh, bạn có thể tải lại ảnh gốc.

Nếu bạn đang sử dụng WPF, bạn có thể thử sử dụng DecodePixelWidth và DecodePixelHeight. Có thể có một tương đương trong winforms

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