повысьте взаимоисключающий массив потоков

Моя проблема, мне обновили блочную матрицу несколько потоков. Несколько потоков могут обновлять непересекающийся блок за один раз, но в целом могут быть условия состязания. прямо сейчас матрица заблокирована с помощью единственной блокировки.

Вопрос, действительно ли это возможно (и если это, как?) для реализации эффективного массива блокировок, так, чтобы только части матрицы, возможно, заблокированной за один раз.

Рассматриваемая матрица может стать довольно большой на порядке 50^2 блоки. мое исходное предположение состоит в том, чтобы использовать, динамично выделяют вектор/карту взаимных исключений.

Это - хороший подход? Лучше использовать несколько условных переменных вместо этого? Существует ли лучший подход?

6
задан alfC 8 July 2018 в 21:53
поделиться

2 ответа

Используйте одинарный замок. Но вместо того, чтобы использовать его для защиты всей матрицы, используйте его для защиты std :: set (или boost :: unordered_set ), который сообщает, какие блоки «заблокированы».

Что-то вроде этого.

class Block;

class Lock_block
{
public:
   Lock_block( Block& block ) : m_block(&block)
   {
      boost::unique_lock<boost::mutex> lock(s_mutex);
      while( s_locked.find(m_block) != s_locked.end() )
      {
         s_cond.wait(lock);
      }
      bool success = s_locked.insert(m_block).second;
      assert(success);
   }

   ~Lock_block()
   {
      boost::lock_guard<boost::mutex> lock(s_mutex);
      std::size_t removed = s_locked.erase(m_block);
      assert(removed == 1);
      s_cond.notify_all();
   }
private:
   Block* m_block;

   static boost::mutex s_mutex;
   static boost::condition s_cond;
   static std::set<Block*> s_locked;
};
7
ответ дан 16 December 2019 в 21:34
поделиться

Вы можете использовать несколько подходов:

  1. Предварительно выделить массив, если CriticalSection / Mutexes (2500 - это не так много), и использовать индекс блока в качестве индекса блокировки для сбора блока доступ; перед обновлением заблокируйте все блоки, которые вы хотите изменить; сделать обновление; unlock;

  2. Если время вычисления значительно больше, чем блокировка / разблокировка, скопируйте содержимое блока в контекст потока и оставьте блок разблокированным в течение этого времени; перед обновлением блока заблокируйте его снова и убедитесь, что он не обновлялся другим потоком (если это актуально для этого); если он был обновлен другим потоком, повторите операцию;

  3. Если размер содержимого блока небольшой, используйте атомарный обмен данными для обновления содержимого блока, блокировки не требуются; просто не уверен, что вы используете данные из одного блока для вычисления данных для другого, в этом случае требуется блокировка всех обновленных блоков;

  4. Есть ли операция чтения в матрице? Если да, используйте блокировки чтения / записи для повышения производительности.

1
ответ дан 16 December 2019 в 21:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: