2015-06-13 2 views
0

Я столкнулся с этой странной ошибкой в ​​многопоточной программе C++ на Linux. Многопоточная часть в основном выполняет цикл. Одна итерация сначала загружает файл sift, содержащий некоторые функции. И затем он запрашивает эти функции против дерева. Поскольку у меня много изображений, я использовал несколько потоков для выполнения этого запроса. Вот фрагменты кода.Многопоточная производительность падает после нескольких операций

struct MultiMatchParam 
{ 
    int thread_id; 
    float *scores; 
    double *scores_d; 
    int *perm; 
    size_t db_image_num; 
    std::vector<std::string> *query_filenames; 
    int start_id; 
    int num_query; 
    int dim; 
    VocabTree *tree; 
    FILE *file; 
}; 

// multi-thread will do normalization anyway 
void MultiMatch(MultiMatchParam &param) 
{ 
    // Clear scores 
    for(size_t t = param.start_id; t < param.start_id + param.num_query; t++) 
    { 
     for (size_t i = 0; i < param.db_image_num; i++) 
      param.scores[i] = 0.0; 

     DTYPE *keys; 
     int num_keys; 

     keys = ReadKeys_sfm((*param.query_filenames)[t].c_str(), param.dim, num_keys); 

     int normalize = true; 
     double mag = param.tree->MultiScoreQueryKeys(num_keys, normalize, keys, param.scores); 

     delete [] keys; 
    } 
} 

Я запускаю это на 8-ядерном процессоре. Сначала он работает отлично, а использование процессора почти 100% на всех 8 ядрах. После того, как каждый поток запросил несколько изображений (около 20 изображений), неожиданно производительность (использование процессора) резко падает до 30% во всех восьми ядрах.

Я сомневаюсь, что ключ к этой ошибке касается этой строки кода.

double mag = param.tree->MultiScoreQueryKeys(num_keys, normalize, keys, param.scores); 

Так как если я заменил его на другие дорогостоящие операции (например, большой для цикла, содержащий sqrt). Использование процессора всегда на 100%. Эта функция MultiScoreQueryKeys выполняет сложную операцию над деревом. Поскольку все восемь ядер могут читать одно и то же дерево (без операции записи на это дерево), мне интересно, имеет ли операция чтения какой-то эффект блокировки. Но он не должен иметь этого эффекта, потому что у меня нет операций записи в этой функции. Кроме того, операции в цикле в основном одинаковы. Если бы он блокировал использование процессора, это произошло бы в первых нескольких итерациях. Если вам нужно посмотреть подробности этой функции или другой части этого проекта, сообщите мне.

+0

Ваш код содержит кучу вещей, которые, вероятно, не имеет значения, тогда как другие части отсутствуют. Извлеките пример mimal, как https://stackoverflow.com/help/how-to-ask. –

+0

Как насчет использования профилировщика, чтобы проверить, что там происходит? – doqtor

+0

Профилировщик должен помочь сузить это. Но, учитывая характер поведения, похоже, что есть блокировка потока где-то с большим количеством времени, затрачиваемым на блокировку, чем дольше этот код работает, что приводит к большей конкуренции и сокращению использования процессора, чем дольше он работает. Поэтому я искал бы общий ресурс/блокировку где-то с большим количеством накопленной работы, а внутри блокировки - дольше, чем это работает. –

ответ

0

Использование станд :: асинхронной() вместо дзета :: SimpleLock блокировки

+0

Этот замок - это наша собственная реализация, которая не имеет ничего общего с этим снижением производительности. Даже если я прокомментирую часть «блокировки» (запись в файл), использование процессора будет по-прежнему резко сокращаться после нескольких итераций. –