Я столкнулся с этой странной ошибкой в многопоточной программе 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 ¶m)
{
// 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 выполняет сложную операцию над деревом. Поскольку все восемь ядер могут читать одно и то же дерево (без операции записи на это дерево), мне интересно, имеет ли операция чтения какой-то эффект блокировки. Но он не должен иметь этого эффекта, потому что у меня нет операций записи в этой функции. Кроме того, операции в цикле в основном одинаковы. Если бы он блокировал использование процессора, это произошло бы в первых нескольких итерациях. Если вам нужно посмотреть подробности этой функции или другой части этого проекта, сообщите мне.
Ваш код содержит кучу вещей, которые, вероятно, не имеет значения, тогда как другие части отсутствуют. Извлеките пример mimal, как https://stackoverflow.com/help/how-to-ask. –
Как насчет использования профилировщика, чтобы проверить, что там происходит? – doqtor
Профилировщик должен помочь сузить это. Но, учитывая характер поведения, похоже, что есть блокировка потока где-то с большим количеством времени, затрачиваемым на блокировку, чем дольше этот код работает, что приводит к большей конкуренции и сокращению использования процессора, чем дольше он работает. Поэтому я искал бы общий ресурс/блокировку где-то с большим количеством накопленной работы, а внутри блокировки - дольше, чем это работает. –