2

現在、複数の画像を一度に読み込んで変換するパイプラインに取り組んでいます。これは同時に多くの画像 (1440) で発生しているため、メモリ フットプリントが非常に大きくなります。そのため、setrlimit に基づいてメモリ管理システムを実装しようとしましたが、生成されたスレッド (std::thread) は喜んで制限を無視するため、影響はないようです。スレッド化された関数 - 最終的にプログラムが強制終了されます。制限を設定するために使用するコードは次のとおりです。

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を使用しています。man ページには、 setrlimit がプロセス全体に影響を与えると記載されているため、スレッドが影響を受けないように見える理由がわかりません。

編集:ちなみに、上記の関数は main() の最初で呼び出されます。

4

1 に答える 1

1

この問題は、完全に独立した 2 つのコンポーネントで構成されていたため、見つけるのが非常に困難でした。

  1. 私の実行可能ファイルは -fomit-frame-pointer でコンパイルされました。これにより、制限がリセットされます。次の例を参照してください。

    /* 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 にプッシュします。

于 2014-05-12T13:38:32.863 に答える