Параллельный доступ к данным

Тема в разделе "WASM.WIN32", создана пользователем float, 15 сен 2011.

  1. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    Какие ситуации могут вызвать исключения при выполнении доступа к данным из разных потоков? Наверное я разучился пользоваться поиском, но конкретного ответа не нашел. Interlocked функции делают безопасным запись данных из разных потоков, а как быть с остальными ситуациями типа чтение+чтение, чтение+выполнение чтение+запись одних и тех же данных? Или в этом случае исключение не будет вызвано?

    p.s. про спин-блокировки и крит секции знаю, просто хочу узнать, можно ли обойтись без них
     
  2. slesh

    slesh New Member

    Публикаций:
    0
    Регистрация:
    6 фев 2009
    Сообщения:
    214
    Если выполняется в единый момент времени только чтение и/или выполнение то блокировка не нужна.
    Если запись есть еще в этот момент, то тогда всё надо по нормальному обернуть.
    Interlocked если нужно математические операции простые делать
    Иначе mutext и критические секции используй
     
  3. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    У меня примерно так реализовано:
    volatile int var1;

    void potok1()
    {
    while(1)
    {
    if(var1)
    {
    //action...
    }
    }
    }

    void potok2()
    {
    while(1)
    {
    //...action
    int register result = //...action
    InterlockedExchange(&var1,result);
    }
    }

    т.е. второй поток пишет через Interlocked, а другой читает напрямую. Это обязательно оборачивать в крит секцию?
     
  4. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    Чтобы не плодить тем, задам тут сразу еще один релевантный вопрос. Из-за потока, выполняющего в цикле операции с данными начинает тормозить основной поток, хотя я ему присвоил IDLE(-15) приоритет. Или этого не достаточно?
     
  5. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Простую запись в (выравненную по умолчанию) int var1 даже в Interlocked не обязательно оборачивать, не говоря уж о критсекции
    PS: Interlocked-операции нужны, когда нужно за один прием прочитать существующее значение и затем его изменить\переписать. А ты просто пишешь, и к тому же пишущий поток у тебя всего один
     
  6. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    ок, спасибо.


    По поводу 2го вопроса.

    добавил отключение Priority Boost, в конце каждой итерации добавил SwitchToThread(); но должного эффекта нет, даже наоборот, чуть сильнее начал тормозить основной поток. Или же все таки нужно разбавить этот поток Sleep'ом?
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Мда, типа ремикс басни Крылова "Мартышка и API"?! :lol:
    Чтобы ничего не тормозило, потоки должны работать максимально независимо, а не дергать постоянно общую изменяемую переменную (и тем более не бодаться постоянно за захват критсекций и т.п), т.к. после каждого изменения var1 на одном из ядер, она (вместе со всей 64-байтной линейкой) удаляется из кэшей первого уровня (L1) других ядер, и при последующем чтении грузится заново через общий кэш 2-го или 3-го уровня, что ес-но намного медленнее.
    А задавать в этом случае всякие приоритеты, бусты, свичи и слипы ва-аще не к селу, т.к. это лишь искуственно добавляет тормозов
     
  8. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    Вы предлагаете не трогать приоритеты и вообще никак не изменять свойства потока, а только убрать общий доступ к переменной из потоков?

    А если у меня стоит задача проверки памяти? Получается я из этого потока читаю всю память, которая (возможно) исполняется и на основном потоке. А в основной поток впихнуть проверку памяти тоже не вариант, потому как при синхронном выполнении тормоза те же и еще и хуже.
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Не предлагаю, а "требую" :)
    А также не заниматься бестолковым "цитированием" = полным дублированием постов, т.к. это той же оперы про мартышку ;)

    Если он не нужен, то конечно убрать. Если же нужен, то подумать как уменьшить частоту обращения к этой переменной. Ты хоть на реальной задаче все это проверяешь или на пустых циклах без всяких action?

    И что из этого? Исполнение это то же чтение, а читать неизменяемую память могут сколько угодно потоков без всяких тормозов. Или у тебя модифицируемый код?
     
  10. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    Код не модифицируемый, читаю только секции кода, но тормоза есть всеравно. Вы хотите сказать, что вот такой поток не будет выжирать процессорное время?

    void thread1()
    {
    while(1);
    }
     
  11. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Что значит "выжирать"? Он будет просто "бестолково" крутиться в цикле и греть процессор - если тебе именно это нужно, то ОК, значит "так и задумано". В противном случае - это глупость

    Ты бы лучше конкретную задачку пояснил, а не задавал бы обще-риторические вопросы. О каких "тормозах" ты говоришь? У тебя гуи-шная прога и при сканировании памяти перерисовка окон висит\тормозит? Или наоборт слишком часто пытаешься какие-то данные отображать (типа прогресса) и в итоге время сканирования увеличивается в разы?
     
  12. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    Игра, однопоточная. окно D3D, при запуске параллельного потока, читающего всю память (конкретно - секции кода основного модуля и некоторых системных по типа kernel32/user32) снижается FPS. А задача в том, чтобы на fps не влияло, каким угодно образом.
     
  13. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ну а общая переменная то зачем нужна? Раз FPS важнее, то и пусть себе второй поток "по тихому" память сканирует, пока не закончит или не найдет чего "подозрительного".
    Хотя если при этом будет притормаживать общий доступ к ОЗУ, то может и придется искусственно снизить скорость сканирования, если это допустимо
     
  14. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    Вот как раз я и говорил об искусственном снижении скорости сканирования. Если вставить слипы, то как лучше это сделать, после сканирования 1 блока или чаще, и вообще, помогут ли слипы?

    ну и что делать если мой поток засаспендят?
     
  15. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ага, а другие должны были догадаться, что скрывается за твоими action и нафиг тебе сдалась var1?!

    Не знаю. Тут по идее нужно как-то привязываться к работе основного потока, чтобы создать ему "все условия". Может попробовать это все не на разных потоках, а на файберах одного потока замутить, тогда и никому не придет в голову ничего суспендить ;)
     
  16. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    Спасибо, буду читать про файберы, главное что я узнал - вв принципе, что приоритеты потоков мне не помогут.
     
  17. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    В твоем случае, с приотритетами имеет смысл поэкспериментировать, если привязать жестко оба потока к одному ядру, тогда второй поток будет работать только во время простоя основного. Если же позволять им работать на разных ядрах, то если в системе нет других активно работающих потоков, то твой idle-поток все равно будет крутиться как обычный normal на свободном ядре
     
  18. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    2leo:
    перечитал соответствующие главы у рихтера, и пришел к такому же выводу. Но, на данный момент меня уже полностью устраивает решение на файберах, по скорости и по остальным параметрам.

    Чуть позже еще попробую реализовать тоже самое в отдельном потоке, с помощью CreateEvent+PulseEvent.