Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Как "сохранить скорость" CreateFileMapping()?

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2

Открыть новую тему     Написать ответ в эту тему

mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Из Рихтера:

Цитата:
В Windows всегда было много механизмов, позволяющих приложениям легко и быс тро разделять какие-либо данные. К этим механизмам относятся RPC, COM, OLE, DDE, оконные сообщения (особенно WM_COPYDATA), буфер обмена, почтовые ящики, сокеты и т. д. Самый низкоуровневый механизм совместного использования данных на одной машине — проецирование файла в память. На нем так или иначе базируются все перечисленные мной механизмы разделения данных Поэтому, если Вас интересует максимальное быстродействие с минимумом издержек, лучше всего применять именно проецирование.

Я использую CreateFileMapping (...) для более быстрого "разговора" 2-х процессов в Real Time на одном PC.
Данных немного (время и значение), 1-й процесс - только пишет, 2-ой процесс - только читает... Актуальны только последние значения.  
Главная - программа заказчика (2-ой процесс), которая хочет использовать мою dll для записи определенных данных, а затем читать эти данныe через предоставленный мной интерфейс (мою dll) с максимально возможной скоростью. Xендлa читающего треда заказчика нет.
Если организовать синхронизацию через CEvent - теряем преимущества "скорого" FileMapping...
Какая альтернатива и оптимальное решение?

----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 12:03 30-11-2003
memfam



Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Во первых, раз коммуникация идет через DLL, дешевле всего использовать не FileMapping, а shared memory:
#pragma data_seg("Common")
    __int64 Data = 0;  // обязательно инициализированная переменная
#pragma data_seg()  
и в линкере при сборке dll добавь  /Section:Common,RWS
 
После этого оба процесса, импортирующие этот dll будут видеть одну и ту же память (при условии, что они идут под одним userом).
 
Что касается самой передачи данных, то хотя CEvent и тратит ресурсы, зато он позволяет читающему процессу просыпаться только когда новые данные поступили, а в остальное время не занимать процессор вообще. Если не делать этого, то оба процесса будут работать все время в busy-loop, и это может оказаться еще медленнее чем с CEvent, CMutex и т.п. Правда, если у тебя двухпроцессорная машина или процессор с HyperThreading, тогда это может быть приемлемо.
 
Если ты все же предпочитаешь обойтись без системных средств синхронизации, то быстрее всего будет упаковать все твои данные в 8 байт и использовать команду
   CMPXCHG8B [memory8]
которая *атомарно* проверяет и обменивает 8 байт:
   if (EDX:EAX == memory8) {
       memory8 = ECX:EBX;
   } else {
       EDX:EAX = memory8;
   }
Т.е. и синхронизация, и запись в одном флаконе.
 
Пишущий процесс:
    EDX:EAX = [Data];
    for(;;) {
       // подготовка данных
       ECX:EBX = очередные данные;
       CMPXHG8 [Data]; //теперь данные в памяти,
                                  //т.к. EDX:EAX было равно содержимому Data
       EDX=ECX;
       EAX=EBX;
    }
 
Читающий процесс
    for(;;) {
       EDX:EAX = -1;     //заведомо несуществующие данные
       CMPXHG8 [Data]; //данные загружены в EDX:EAX  
                                  //т.к. EDX:EAX не было равно содержимому Data
       // обработка данных из EDX:EAX  
    }
 
     

Всего записей: 13 | Зарегистр. 01-12-2003 | Отправлено: 14:07 02-12-2003 | Исправлено: memfam, 14:11 02-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
memfam

Цитата:
Во первых, раз коммуникация идет через DLL, дешевле всего использовать не FileMapping, а shared memory

Спорно на счет дешевле... + :
1. это предпочтительно для очень "маленьких" данных
2. Надо учить заказчика пользоваться этим...

Цитата:
упаковать все твои данные в 8 байт и использовать команду  

...время и значение не поместятся...

----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 15:02 02-12-2003
memfam



Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Спорно на счет дешевле... + :  
1. это предпочтительно для очень "маленьких" данных  
2. Надо учить заказчика пользоваться этим...  

Дешевле - наверняка, потому что используется тот же file mapping, но на уровне загрузчика - т.е. средствами ядра. Да и кода писать нужно меньше, и проверять код возврата не надо. Единственный минус - межпользовательский sharing не получится, но если у тебя не сервер, то межпользовательский sharing может требоваться только между сервисами или сервис-аппликация, а это явно не твой случай.
1. Насчет маленьких данных - в расшаренную секцию можно поместить сколько угодно переменных, массивов и т.п. Правда, надо чтобы они были инициализированные.
2. Ну, если надо, так надо. Зачем, кстати если не секрет? Ж-) Разве заказчику не все равно, лишь бы работало?
В любом случае, как именно расшарить данные, это независимый вопрос, и на синхронизацию он не влияетю
 

Цитата:
...время и значение не поместятся...

А вот это и правда хуже. Но выбор между busy-loop и средствами системы все равно придется делать. Я бы сказал, что если только данные не идут непрерывным потоком, лучше использовать системную синхронизацию, иначе один из процессов может не получить достаточно времени и выпасть из синхронизации. Если же данные действительно нужны все время, надо позаботиться о равном приоритете обоих либо использовать двухпроцессорную машину. Сама же синхронизация через busy-loop - штука стандартная:
 
Определяем буфер и семафор в общей памяти (CreateFileMapping тоже подойдет):
   volatile char Buffer[.....];
   volatile LONG Sema = 0;
 
Пишущий процесс:
   for(;;) {
      if (Sema == 0) {
          // Сгенерировать и занести данные в буффер
          InterlockedIncrement (&Sema);
      }
   }
 
Читающий процесс:
   for(;;) {
      if (Sema > 0) {
         // Забрать данные и обработать
         InterlockedDecrement (&Sema);
      }
   }
 
 
 

Всего записей: 13 | Зарегистр. 01-12-2003 | Отправлено: 17:30 02-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
memfam

Цитата:
Единственный минус - межпользовательский sharing не получится

A необходимость "учить заказчика пользоваться этим..."?

Цитата:
Разве заказчику не все равно, лишь бы работало?  

Хочет грамотно использовать это...

----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 19:50 02-12-2003
memfam



Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ну ладно. Когда мне это было нужно в последний раз, я сделал расшаренную секцию. И кстати, потом пришлось переписать с file mappingом, но только потому, что аппликации должны были видеть друг друга, даже если их запускали разные пользователи на терминал сервере.
 
Надеюсь, то что я писал, чем-нибудь тебе помогло
Желаю успеха.

Всего записей: 13 | Зарегистр. 01-12-2003 | Отправлено: 21:19 02-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
memfam

Цитата:
Надеюсь, то что я писал, чем-нибудь тебе помогло  

Общение всегда очень полезно.

Цитата:
Желаю успеха.

Спасибо! Будем стараться.


----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 22:47 03-12-2003
drobitko

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
А что в CEvent - такого медленного? Можно ведь и на Win32 API все написать, если не устраивает CEevent.
 
И чем он замедляет FileMapping?
 
С наилучшими пожеланиями,
Александр.

Всего записей: 83 | Зарегистр. 10-02-2003 | Отправлено: 13:34 04-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
drobitko

Цитата:
Можно ведь и на Win32 API все написать, если не устраивает CEevent.  

От этого ничего не изменится...
А в отношении скорости CEevent и FileMapping - это 2 разные весовые категории...
Читай Рихтера...

----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 21:30 04-12-2003
drobitko

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
mihas83
 
 
Причем тут разные весовые категории.
 
Event -  в данном случае нужен для синхронизации доступа к разделяемому ресурсу.  
 
В данном случае если доступ возможен, то операция ожидания на Event пройдет практически мгновенно. Дальше будет работать FileMapping.
 
Если же доступ не возможен, то операция ожидания будет идти ровно столько сколько разделяемый ресурс будет занят. А потом предоставиться доступ и в ход пойдет FileMapping.
 
Так где здесь использование Event приводит к потере преимущества FileMapping?

Всего записей: 83 | Зарегистр. 10-02-2003 | Отправлено: 11:54 05-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
drobitko

Цитата:
операция ожидания на Event пройдет практически мгновенно.  

Сомнения именно в этом!

----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 12:04 05-12-2003
drobitko

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
mihas83
 

Цитата:
Цитата:операция ожидания на Event пройдет практически мгновенно.
 
Сомнения именно в этом!  

 
Ну так можно проверить насколько это быстро это работает.
 
С другой стороны нет гарантии, что твой алгоритм будет работать быстрее системного ( и правильно)?! Тем более, что системный вызов организован на уровне ядра.
 

Всего записей: 83 | Зарегистр. 10-02-2003 | Отправлено: 12:25 05-12-2003 | Исправлено: drobitko, 12:27 05-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
drobitko

Цитата:
Ну так можно проверить насколько это быстро это работает.  

Ты сам тестировал?

Цитата:
С другой стороны нет гарантии, что твой алгоритм будет работать быстрее системного  
 Согласен.


----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 12:34 05-12-2003
drobitko

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
mihas83
 

Цитата:
Цитата:Ну так можно проверить насколько это быстро это работает.  
 
Ты сам тестировал?  

 
Когда-то, очень давно еще на NT4SP3. Тогда у меня нареканий не было, но точных цифр за давностью лет дать не могу .
 
Не думаю, что ситуация с тех пор сильно ухудшилась.
 
Важный момент, теcтировал я на чистом Win32 API, как работает CEvent не знаю, может у него все и дольше.

Всего записей: 83 | Зарегистр. 10-02-2003 | Отправлено: 13:23 05-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
drobitko

Цитата:
Важный момент, теcтировал я на чистом Win32 API, как работает CEvent не знаю, может у него все и дольше.  

Реализовать на чистом Win32 API не проблема...
Сейчас заказчик повернул задачу в другое русло - "посадить" эту работу в отдельную функцию "разговора с железом", которую они могут вызывать...
Сам вызов "оградить" критическими секциями...  


----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 13:39 05-12-2003 | Исправлено: mihas83, 13:41 05-12-2003
memfam



Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
 
Цитата:Цитата:Ну так можно проверить насколько это быстро это работает.    
 
Ты сам тестировал?  
 
 
Когда-то, очень давно еще на NT4SP3. Тогда у меня нареканий не было, но точных цифр за давностью лет дать не могу .  
 
Не думаю, что ситуация с тех пор сильно ухудшилась.  
 
Важный момент, теcтировал я на чистом Win32 API, как работает CEvent не знаю, может у него все и дольше.  

 
CEvent (или HANDLE, возвращенный CreateEvent) - это всегда kernel object, поэтому любое действие с ним - это минимум 2 task-switch'а - один из user mode в kernel, другой обратно. Так что это будет раз в 100 медленнее, чем при использовании user-mode команды (например, через вызов Interlocked... функций, или напрямую __asm cmpxhg).
Другое дело (как я уже писал), что на однопроцессорной машине две одновременно бегущие thread будут все время переключаться - а это тоже task-switch.

Всего записей: 13 | Зарегистр. 01-12-2003 | Отправлено: 23:18 05-12-2003 | Исправлено: memfam, 23:19 05-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
memfam

Цитата:
Так что это будет раз в 100 медленнее, чем при использовании user-mode команды

Вот и Рихтер так утверждает...

----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 23:31 05-12-2003
YaroslavTatarenko

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
CEvent (или HANDLE, возвращенный CreateEvent) - это всегда kernel object, поэтому любое действие с ним - это минимум 2 task-switch'а - один из user mode в kernel, другой обратно. Так что это будет раз в 100 медленнее, чем при использовании user-mode команды (например, через вызов Interlocked... функций, или напрямую __asm cmpxhg).  
Другое дело (как я уже писал), что на однопроцессорной машине две одновременно бегущие thread будут все время переключаться - а это тоже task-switch

 
Абсолютно верно, мало того вызов SetEvent также не шустрый, но нужно определится со следующим: при Loop с Interlockedxxx величина CPU будет весьма велика, а при WaitForxxx и SetEvent - минимальна. Что нужно заказчику - пока не ясно. Realtime системы не пишутся на стандартном kernel NT да и использование межпроцессного взаимодействия - не лучший способ. Если же это не realtime, а сервер с большим объемом входящих данных, то можно смело использовать CEvent и CMutex, и просто... попросить получше процессоры (поверьте мне, если есть вариант купить 2 новых процессора по 1000, то лучше сделать это, чем заставлять 5-6 месяцев разработчику с з/п в 600-700 оптимизировать по тактам процессора программу? Элементарная арифметика!) В этом случае можно даже использовать Socket

Всего записей: 2 | Зарегистр. 08-12-2003 | Отправлено: 12:54 10-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Новый поворот проблемы:
Oткрывать в отдельном процессе огромные  tiff файлы (библиотекой ImageGear фирмы AccuSoft) и потом "кусками" - линиями передавать буфферы другому процессу...
Сталкивался ли кто-то?

----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 11:26 12-12-2003
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
...библиотекa ImageGear фирмы AccuSoft возвращет свои (доморощенные):
 
typedef DWORD HIGEAR; // Handle to an ImageGear image  
typedef HIGEAR FAR *LPHIGEAR; // Far pointer to HIGEAR,
 
,a остальные функции библиотеки работают с ним...
А как пройдет "подсовывание" его (HIGEAR) - "вместо" HANDLE hFile = CreateFile(...)  
в HANDLE hMap = CreateFileMapping(HIGEAR, ...); ? "Прокатит"?  
Hy и главное: родные функции ImageGear как заставить потом работать с hMap ?  
Кастинг hMap на HIGEAR не поможет?

----------
Мы знаем: время растяжимо. Оно зависит от того,
Какого рода содержимым Вы заполняете его. (C. Маршак)

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 09:48 15-12-2003
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Как "сохранить скорость" CreateFileMapping()?


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru