2014-04-19 8 views
2

В настоящее время я работаю над конвейером, который загружает и преобразует сразу несколько изображений. Так как это происходит со многими изображениями одновременно (1440), объем памяти довольно тяжелый. Поэтому я попытался внедрить систему управления памятью на основе setrlimit, однако она, похоже, не влияет на порожденные потоки (std :: thread), поскольку они с удовольствием игнорируют ограничение - я знаю это из-за вызовов getrlimit() в и в конечном итоге привести к тому, что моя программа будет убита. Вот код, который я использую для установки предела:setrlimit() не влияет на порожденный std :: threads

void setMemoryLimit(std::uint64_t bytes) 
{ 
    struct rlimit limit; 
    getrlimit(RLIMIT_AS, &limit); 

    if(bytes <= limit.rlim_max) 
    { 
     limit.rlim_cur = bytes; 
     std::cout << "New memory limit: " << limit.rlim_cur << " bytes" << std::endl; 
    } 
    else 
    { 
     limit.rlim_cur = limit.rlim_max; 
     std::cout << "WARNING: Memory limit couldn't be set to " << bytes << " bytes" << std::endl; 
     std::cout << "New memory limit: " << limit.rlim_cur << " bytes" << std::endl; 
    } 

    if(setrlimit(RLIMIT_AS, &limit) != 0) 
     std::perror("WARNING: memory limit couldn't be set:"); 

    // included for debugging purposes 
    struct rlimit tmp; 
    getrlimit(RLIMIT_AS, &tmp); 
    std::cout << "Tmp limit: " << tmp.rlim_cur << " bytes" << std::endl; // prints the correct limit 
} 

Я использую Linux. На странице руководства указано, что setrlimit влияет на весь процесс, поэтому я не знаю, почему потоки, похоже, не затронуты.

Редактировать: Кстати, вышеприведенная функция вызывается в самом начале main().

+2

Помимо «фактического вопроса», почему, по вашему мнению, это правильное решение? Разумеется, правильное решение состоит в том, чтобы не запускать столько потоков или загружать сразу столько изображений или что бы вы ни делали, чтобы ограничить использование памяти? Предполагая, что 'setrlimit' действительно работал, произойдет то, что ваш процесс либо будет убит, либо не сможет выделить память где-то« случайным », что, очевидно, довольно ужасно, чтобы справиться с проблемой ... –

+0

Я проверяю доступную память перед загрузкой. Если памяти нет, загрузка останавливается - по крайней мере теоретически. Моя проблема в том, что существующие ограничения игнорируются потоками, и я не знаю, почему и как их обойти. –

+0

Пожалуйста, покажите пример минимальной сборки, демонстрирующий проблему. –

ответ

1

Проблема была довольно трудно найти, как он состоял из двух полностью независимых компонентов:

  1. Мой исполняемый файл был скомпилирован с -fomit-кадр-указатель. Это приведет к сбросу предела. Смотрите следующий пример:

    /* rlimit.cpp */ 
    #include <iostream> 
    #include <thread> 
    #include <vector> 
    
    #include <sys/resource.h> 
    
    class A 
    { 
        public: 
         void foo() 
         { 
          struct rlimit limit; 
          getrlimit(RLIMIT_AS, &limit); 
          std::cout << "Limit: " << limit.rlim_cur << std::endl; 
         } 
    }; 
    
    int main() 
    { 
        struct rlimit limit; 
        limit.rlim_cur = 500 * 1024 * 1024; 
        setrlimit(RLIMIT_AS, &limit); 
        std::cout << "Limit: " << limit.rlim_cur << std::endl; 
    
        std::vector<std::thread> t; 
    
        for(int i = 0; i < 5; i++) 
        { 
         A a; 
         t.push_back(std::thread(&A::foo, &a)); 
        } 
    
        for(auto thread : t) 
         thread.join(); 
    
        return 0; 
    } 
    

    Выходы:

    > g++ -std=c++11 -pthread -fomit-frame-pointer rlimit.cpp -o limit 
    > ./limit 
    Limit: 524288000 
    Limit: 18446744073709551615 
    Limit: 18446744073709551615 
    Limit: 18446744073709551615 
    Limit: 18446744073709551615 
    Limit: 18446744073709551615 
    
    > g++ -std=c++11 -pthread rlimit.cpp -o limit 
    > ./limit 
    Limit: 524288000 
    Limit: 524288000 
    Limit: 524288000 
    Limit: 524288000 
    Limit: 524288000 
    Limit: 524288000 
    
  2. Для части обработки изображения я работаю с OpenCL. По-видимому, реализация NVIDIA вызывает setrlimit и ограничивает rlim_max.