2010-03-29 12 views
8

Goalnajbardziej efektywny sposób do wysyłania obrazów w całej przetwarza

Pass obrazów generowanych przez jeden proces efektywnie i przy bardzo dużej prędkości do innego procesu. Oba procesy działają na tym samym komputerze i na tym samym pulpicie. System operacyjny może być WinXP, Vista i Win7.

Szczegółowy opis

Pierwszy proces wyłącznie w celu kontrolowania komunikacji z urządzeniem, które wywołuje obrazy. Te obrazy mają rozmiar około 500 x 300 pikseli i mogą być aktualizowane do kilkuset razy na sekundę. Drugi proces potrzebuje tych obrazów, aby je przetworzyć. Pierwszy proces wykorzystuje zewnętrzny interfejs API do malowania obrazów z urządzenia na HDC. Ten HDC musi być dostarczony przeze mnie.

Uwaga: między dwoma procesami istnieje już połączenie otwarte. Komunikują się za pośrednictwem anonimowych potoków i udostępniają widoki odwzorowanych obrazów w pamięci.

Myśli

Jak bym to osiągnąć z tak mało pracy, jak to możliwe? Mam na myśli zarówno pracę dla komputera, jak i dla mnie (oczywiście;)). Używam Delphi, więc może jest jakiś komponent dostępny do tego? Myślę, że zawsze mógłbym namalować do dowolnego HDC komponentu obrazu, zapisać zawartość do strumienia pamięci, skopiować zawartość za pomocą pliku odwzorowanego w pamięci, rozpakować ją po drugiej stronie i namalować tam do docelowego HDC. Przeczytałem również o interfejsie IPicture, który może być użyty do zbierania obrazów. Potrzebuję go tak szybko, jak to możliwe, więc im mniej, tym lepiej. Nie chcę, aby maszyna była zestresowana tylko przez kopiowanie niektórych obrazów.

Jakie są Twoje pomysły? Doceniam każdą myśl na ten temat!

+1

jeśli obraz jest aktualizowany kilkaset razy na sekundę, możesz zajrzeć do istniejących technik przetwarzania wideo w celu obsługi danych wideo o dużej przepustowości w przeciwieństwie do przetwarzania obrazu. –

Odpowiedz

1

OK Wygląda na to, że pliki mapowane w pamięci i rury są właściwą drogą. To nie jest tak źle, ponieważ dwa procesy już mają wspólny MMF i dwie rury (w przypadku komunikacji dwukierunkowej). Jedyne, co pozostało do rozwiązania, to jak przekazać dane przy jak najmniejszej liczbie operacji kopiowania.

konstrukcję, która pracuje dobrze się następująco (przepływ sekwencyjne)

Sposób 1 (chce obrazu) sygnał

  • dać przetwarzania 2 (przewodem 1) do przechowywania obrazu w pamięci wspólnej
  • iść spać i czekać na odpowiedź (blokowanie odczytu z rury 2)

Process 2 (zapewnia obrazy)

  • na sygnał (poprzez rurę 1) obudzić i powiedzieć urządzenia sprzętowego malować do HDC 1 (jest to poparte pamięci współdzielonej, patrz niżej)
  • dać sygnał do przetwarzania 1 (poprzez rurę 2)
  • iść spać i czekać do nowej pracy (poprzez rurę 1)

Process 1 (chce obraz)

  • na sygnał (poprzez rurę 2) obudzić i farby z pamięci współdzielonej do połączenia HDC 2

Teraz na transfer obrazu poprzez wspólną pamięcią (moim celem było wykorzystać nie więcej niż jedna dodatkowa operacja kopiowania):

Procesie 2 tworzy HBITMAP poprzez CreateDIBSection i zapewnia uchwyt mapowanie pliku i przesunięcie zmapowanego widoku. W ten sposób dane obrazu znajdują się we wspólnej pamięci. Tworzy to HBITMAP, który jest wybrany do HDC 1 (który jest również tworzony przez proces 2) i który będzie używany od teraz przez proces 2.

Proces 1 używa StretchDIBits ze wskaźnikiem do pamięci zmapowanego widoku (jak opisano here). Wydaje się, że jest to jedyna funkcja pobierania bitów z pamięci bezpośrednio do innego HDC (w tym przypadku HDC 2). Inne funkcje skopiowałyby je najpierw do bufora pośredniego, zanim można by je przenieść do ostatecznego HDC.

Ostatecznie wydaje się, że bity potrzebne do przeniesienia są około dwa razy większe niż na początku. Ale myślę, że to jest tak dobre, jak to możliwe, chyba że udostępnienie uchwytów GDI pomiędzy procesami będzie możliwe.

Uwaga: Użyłem potoków zamiast sygnałów, ponieważ muszę również przesłać dodatkowe dane.

11

Użyj Memory Mapped File.

Aby uzyskać odniesienie do Delphi, zobacz Memory-mapped Files in Delphi i Shared Memory in Delphi.

Aby uzyskać bardziej uniwersalne podejście, można spojrzeć na użycie rur lub przesłanie danych bitmapowych za pośrednictwem protokołu TCP. Umożliwiłoby to łatwiejszą dystrybucję danych obrazu między węzłami, jeśli to konieczne.

+0

Tak, mógłbym to zrobić z plikiem mapowanym w pamięci. Nadal musiałbym namalować obraz do mojego HDC, przekształcić obraz do MMF, odczytać go ponownie po drugiej stronie i namalować obraz do ostatecznego HDC. Wydaje się, że są to 4 operacje kopiowania, w których kiedyś było tylko 1. Dlatego szukam bardziej wydajnego sposobu. Ale jeśli nie ma takiej drogi, to myślę. –

4

Użyj pamięci współdzielonej, aby przekazać dane obrazu i coś innego (nazwane potoki, gniazda, ...), aby skoordynować przekazywanie.

3

W niektórych przypadkach można przekazywać uchwyty HBITMAP między procesami. Widziałem to już wcześniej (tak, na XP/Vista) i byłem zaskoczony, jak wszyscy inni w zespole, kiedy pokazał mi jeden z moich współpracowników.

Jeśli pamięć mnie nie myli, wierzę, to będzie działać, jeśli HBITMAP przeznaczono jedną z funkcji GDI (CreateBitmap, CreateCompatibleBitmap, CreateDIBitmap, etc ...) HBIMAP obsługuje stworzony przez funkcji LoadBitmap nie będzie działać jak to tylko wskaźnik do zasobu w-proc.

To, i myślę, że kiedy dzielisz HBITMAP z drugim procesem, nie próbuj robić nic specjalnego poza zwykłymi operacjami BitBlt.

Przynajmniej to jest to, co pamiętam. Mamy szczęście, ponieważ nasze biblioteki graficzne zostały już napisane, aby zarządzać wszystkimi obrazami jako HBITMAP.

YMMV

+0

+1 Nie użyłbym go, ale nadal jest interesujący. –

+1

To jest rzeczywiście interesujące, chociaż nie mogłem go również użyć bez złych odczuć. Wygląda na to, że przekazywanie uchwytów GDI pomiędzy procesami przypomina nieco hazard - nie powinno działać, ale zdaje się, że czasami. (Zobacz http://stackoverflow.com/questions/2499487/sharing-hdc-between-different-processes, gdzie najpierw zapytałem o to podejście, ponieważ miałem nadzieję, że będzie to łatwe.) –

+0

Ale co z tego: http://stackoverflow.com/a/2500975/893350 Próbowałem tego i otrzymuję "Ogólny błąd wystąpił w GDI +." ErrCode: -2147467259 –

0

Jak widzę to masz dwie opcje:

  1. Pass jest tylko obraz uchwyt/wskaźnik do innego procesu, więc oba procesy działają tylko na jednej kolekcji zdjęć.
  2. Skopiuj zawartość obrazu do innego procesu i od tej pory odtwórz kopię.

To, które podejście jest najlepsze, zależy od Twojego projektu. Najlepsze narzędzie dla obu podejść to "pliki mapowane w pamięci" lub "potoki nazwane". Jest to najszybszy możliwy do zdobycia. Pliki mapowane w pamięci są prawdopodobnie najszybszą formą komunikacji między procesami, ale nie mają wątpliwości, że nie ma w nich wbudowanego paradygmatu "klient-serwer". Dlatego musisz samodzielnie zsynchronizować dostęp do MMF. Nazwane rury z drugiej strony są prawie tak szybkie, ale mają wbudowany paradygmat klient-serwer. Różnica w prędkości pochodzi głównie z tego.

Teraz, ze względu na szybkość udostępniania aktualizacji, pierwsze podejście może być lepsze, ale trzeba uważać na synchronizację między procesami, aby nie zapisywać/zapisywać pojedynczego obrazu w tym samym czasie. Można również użyć buforowania lub innych inteligentnych gier, aby zmniejszyć ruch do minimum. W obliczu tak wysokiego poziomu komunikacji zawsze wskazane jest szukanie sposobów zmniejszenia tego poziomu, jeśli to możliwe.

Aby bardzo szybko wdrożyć IPC na podstawie nazwanych potoków, można użyć mojej implementacji IPC. Jest zorientowany na wiadomości, więc nie musisz martwić się o szczegóły techniczne rury. Używa również puli wątków za kulisami i ma dodatkowe dodatkowe obciążenie. Możesz go przetestować i przekonać się samemu (typowy komunikat trwa 0,1 ms dla pełnego cyklu żądanie-odpowiedź klienta-serwera).

+0

Dzięki za połączenie z implementacją IPC - może to wymagać później, jeśli będziemy musieli przekroczyć granice komputera. Ale mój przypadek użycia jest teraz bardzo wąski. Czytałem kiedyś, że różne domeny mogą powodować problemy z nazwanymi potokami, czy testowałeś to? –

+0

Przetestowałem na dwóch komputerach w tej samej sieci LAN, tej samej domenie. Nie próbowałem innych kombinacji. Używam go do komunikacji między procesami na tym samym komputerze, ponieważ jest łatwiejszy w użyciu niż MMF. Nie musisz wykonywać żadnej synchronizacji. – Runner

Powiązane problemy