Я работаю над довольно большим проектом C++ с большим упором на производительность. Поэтому он использует библиотеку Intel MKL и OpenMP. Недавно я заметил значительную утечку памяти, которую я мог сузить до следующего минимального примера:
#include <atomic>
#include <iostream>
#include <thread>
class Foo {
public:
Foo() : calculate(false) {}
// Start the thread
void start() {
if (calculate) return;
calculate = true;
thread = std::thread(&Foo::loop, this);
}
// Stop the thread
void stop() {
if (!calculate) return;
calculate = false;
if (thread.joinable())
thread.join();
}
private:
// function containing the loop that is continually executed
void loop() {
while (calculate) {
#pragma omp parallel
{
}
}
}
std::atomic<bool> calculate;
std::thread thread;
};
int main() {
Foo foo;
foo.start();
foo.stop();
foo.start();
// Let the program run until the user inputs something
int a;
std::cin >> a;
foo.stop();
return 0;
}
При компиляции с помощью Visual Studio 2013 и выполнении этот код теряет до 200 МБ памяти в секунду (!).
Немного изменив приведенный выше код, утечка полностью исчезнет. Например:
- Если программа не связана с библиотекой MKL (которая здесь явно не нужна), утечки нет.
- Если я скажу OpenMP использовать только один поток (т. е. я установлю переменную среды
OMP_NUM_THREADS
в1
), утечки не будет. - Если я закомментирую строку
#pragma omp parallel
, утечки не будет. - Если я не остановлю поток и не начну его снова с
foo.stop()
иfoo.start()
, утечки не будет.
Я делаю что-то неправильно здесь или я что-то упускаю?
atomic<bool> calculate{false};
вместоatomic<bool> calculate=false;
, посколькуstd::atomic
удалил конструктор копирования, и это необходимо для инициализации копирования даже в случае оптимизации временного. - person Daniel Langr   schedule 15.01.2016calculate
- person oLen   schedule 15.01.2016