Memory management 了解推力(CUDA)内存使用情况

Memory management 了解推力(CUDA)内存使用情况,memory-management,cuda,thrust,Memory Management,Cuda,Thrust,我正在使用cuda/推力库做一些蒙特卡罗模拟。这在一定数量的模拟中非常有效,我得到了一个坏的alloc异常。这似乎没问题,因为我的代码中越来越多的模拟意味着处理越来越大的设备向量。所以我希望这种异常会在某个时候出现 我现在想做的是根据我的GPU上的可用内存设置模拟次数的上限。然后,我可以将工作负载分成一组模拟 因此,在启动我的模拟集之前,我一直在尝试确定问题的大小。不幸的是,当我试图通过简单的例子来理解内存的管理方式时,我得到了令人惊讶的结果 下面是我一直在测试的代码示例: #include &

我正在使用cuda/推力库做一些蒙特卡罗模拟。这在一定数量的模拟中非常有效,我得到了一个坏的alloc异常。这似乎没问题,因为我的代码中越来越多的模拟意味着处理越来越大的设备向量。所以我希望这种异常会在某个时候出现

我现在想做的是根据我的GPU上的可用内存设置模拟次数的上限。然后,我可以将工作负载分成一组模拟

因此,在启动我的模拟集之前,我一直在尝试确定问题的大小。不幸的是,当我试图通过简单的例子来理解内存的管理方式时,我得到了令人惊讶的结果

下面是我一直在测试的代码示例:

#include <cuda.h>
#include <thrust/system_error.h>
#include <thrust/device_vector.h>
#include <thrust/execution_policy.h>
#include <cuda_profiler_api.h>

int main() 
{
    size_t freeMem, totalMem;

    cudaDeviceReset();
    cudaSetDevice(0);

    cudaMemGetInfo(&freeMem, &totalMem);
    std::cout << "Total Memory | Free Memory "<< std::endl;
    std::cout << totalMem << ", " << freeMem << std::endl;

    thrust::device_vector<float> vec1k(1000, 0);

    cudaMemGetInfo(&freeMem, &totalMem);
    std::cout << totalMem << ", " << freeMem << std::endl;

    thrust::device_vector<float> vec100k(100000, 0);

    cudaMemGetInfo(&freeMem, &totalMem);
    std::cout << totalMem << ", " << freeMem << std::endl;

    thrust::device_vector<float> vec1M(1000000, 0);

    cudaMemGetInfo(&freeMem, &totalMem);
    std::cout << totalMem << ", " << freeMem << std::endl;

    return 0;
}
所以基本上

  • 1000个元素的向量(加上所有其他需要的元素)使用1048576字节
  • 100000元素向量也使用1048576字节
  • 1000000元素向量使用4063232字节
我本以为内存使用量会大致随元素数量而变化,但当我预期为“10倍”时,我得到了“4倍”,而这种关系并不适用于1000到100000个元素

因此,我的两个问题是:

  • 有人能帮我理解这些数字吗
  • 如果我无法估计代码将使用的内存量,那么,有什么好的策略可以确保我的程序适合内存
编辑

在Mai Longdong评论之后,我尝试了两个向量,一个是262144个浮点(4字节),另一个是262145。不幸的是,事情看起来不像是直接的“每1MB页面分配”:

  • 第一个向量的大小(262144个浮点):1048576字节
  • 第二个向量的大小(262145个浮点):1179648字节

两者之间的增量为131072字节(或128 KB)。页面大小是可变的吗?这有意义吗?

推力对内存管理没有任何魔力,默认分配器只是
cudamaloc
,您看到的是驱动程序内存管理器页面大小选择算法正在工作。这没有文档记录,也没有迹象表明平台和硬件版本之间的行为是一致的

也就是说,如果我将您的代码扩展为更有用的内容:

#include <iostream>
#include <vector>
#include <thrust/system_error.h>
#include <thrust/device_vector.h>
#include <thrust/execution_policy.h>

void report_mem(size_t allocd, bool first=false)
{
    size_t freeMem, totalMem;
    cudaMemGetInfo(&freeMem, &totalMem);
    if (first) 
        std::cout << "Allocated | Total Memory | Free Memory "<< std::endl;
    std::cout << allocd << ", " << totalMem << ", " << freeMem << std::endl;
}

int main() 
{
    cudaSetDevice(0);

    report_mem(0, true);
    std::vector<size_t> asizes;
    const int nallocs = 10;
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<14);
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<16);
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<18);
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<20);
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<22);

    typedef thrust::device_vector<float> dvecf_t;
    std::vector<dvecf_t*> allocs;
    auto it = asizes.begin();
    for(; it != asizes.end(); ++it) {
        dvecf_t* v = new dvecf_t(*it);
        allocs.push_back(v);
    report_mem(v->capacity() * sizeof(float));
    }
    return 0;
}

我将其解释为,在我测试这个的平台上,分配粒度是1MiB(1048576或2^20字节)。您的平台可能会有所不同。

您阅读了吗?我刚刚阅读了,内容非常丰富,非常感谢。内存分配过程似乎远远不是线性的。或者,好吧,我认为主要的想法是,只要设备向量大小低于某个阈值,并且有足够的内存可用,就会分配相当大的默认内存。重新编辑:实际上,任何64 kB的倍数都是有意义的。我曾经回答过一个问题,页面大小是64KB。无论如何,这没有记录在案。
#include <iostream>
#include <vector>
#include <thrust/system_error.h>
#include <thrust/device_vector.h>
#include <thrust/execution_policy.h>

void report_mem(size_t allocd, bool first=false)
{
    size_t freeMem, totalMem;
    cudaMemGetInfo(&freeMem, &totalMem);
    if (first) 
        std::cout << "Allocated | Total Memory | Free Memory "<< std::endl;
    std::cout << allocd << ", " << totalMem << ", " << freeMem << std::endl;
}

int main() 
{
    cudaSetDevice(0);

    report_mem(0, true);
    std::vector<size_t> asizes;
    const int nallocs = 10;
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<14);
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<16);
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<18);
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<20);
    for(int i=0; i < nallocs; i++) asizes.push_back(1<<22);

    typedef thrust::device_vector<float> dvecf_t;
    std::vector<dvecf_t*> allocs;
    auto it = asizes.begin();
    for(; it != asizes.end(); ++it) {
        dvecf_t* v = new dvecf_t(*it);
        allocs.push_back(v);
    report_mem(v->capacity() * sizeof(float));
    }
    return 0;
}
Allocated | Total Memory | Free Memory 
0, 1073741824, 1007849472
65536, 1073741824, 1006800896
65536, 1073741824, 1006800896
65536, 1073741824, 1006800896
65536, 1073741824, 1006800896
65536, 1073741824, 1006800896
65536, 1073741824, 1006800896
65536, 1073741824, 1006800896
65536, 1073741824, 1006800896
65536, 1073741824, 1006800896
65536, 1073741824, 1006800896
262144, 1073741824, 1005752320
262144, 1073741824, 1005752320
262144, 1073741824, 1005752320
262144, 1073741824, 1005752320
262144, 1073741824, 1004703744
262144, 1073741824, 1004703744
262144, 1073741824, 1004703744
262144, 1073741824, 1004703744
262144, 1073741824, 1003655168
262144, 1073741824, 1003655168
1048576, 1073741824, 1002606592
1048576, 1073741824, 1001558016
1048576, 1073741824, 1000509440
1048576, 1073741824, 999460864
1048576, 1073741824, 998412288
1048576, 1073741824, 997363712
1048576, 1073741824, 996315136
1048576, 1073741824, 995266560
1048576, 1073741824, 994217984
1048576, 1073741824, 993169408
4194304, 1073741824, 988975104
4194304, 1073741824, 984780800
4194304, 1073741824, 980586496
4194304, 1073741824, 976392192
4194304, 1073741824, 972197888
4194304, 1073741824, 968003584
4194304, 1073741824, 963809280
4194304, 1073741824, 959614976
4194304, 1073741824, 955420672
4194304, 1073741824, 951226368
16777216, 1073741824, 934449152
16777216, 1073741824, 917671936
16777216, 1073741824, 900894720
16777216, 1073741824, 884117504
16777216, 1073741824, 867340288
16777216, 1073741824, 850563072
16777216, 1073741824, 833785856
16777216, 1073741824, 817008640
16777216, 1073741824, 800231424