0

我有一个推力代码,它将大量数据(2.4G)加载到内存中,执行计算,结果存储在主机(~1.5G)中,然后释放初始数据,将结果加载到设备中,对其执行其他计算,最后重新加载初始数据。推力代码如下所示:

thrust::host_device<float> hostData;
// here is a code which loads ~2.4G of data into hostData
thrust::device_vector<float> deviceData = hostData;
thrust::host_vector<float> hostResult;
// here is a code which perform calculations on deviceData and copies the result to hostResult (~1.5G)
free<thrust::device_vector<float> >(deviceData);
thrust::device_vector<float> deviceResult = hostResult;
// here is code which performs calculations on deviceResult and store some results also on the device
free<thrust::device_vector<float> >(deviceResult);
deviceData = hostData;

使用我定义的免费功能:

template<class T> void free(T &V) {
    V.clear();
    V.shrink_to_fit();
    size_t mem_tot;
    size_t mem_free;
    cudaMemGetInfo(&mem_free, &mem_tot);
    std::cout << "Free memory : " << mem_free << std::endl;
}

template void free<thrust::device_vector<int> >(thrust::device_vector<int>& V);
template void free<thrust::device_vector<float> >(
    thrust::device_vector<float>& V);

但是,在尝试将 hostData 复制回 deviceData 时出现“thrust::system::detail::bad_alloc' what(): std::bad_alloc: out of memory”错误,即使此时 cudaMemGetInfo 返回该错误我有 ~我的设备有 6G 的可用内存。这是 free 方法的完整输出:

Free memory : 6295650304
Free memory : 6063775744
terminate called after throwing an instance of 'thrust::system::detail::bad_alloc'
what():  std::bad_alloc: out of memory

尽管有很多可用空间,但这似乎表明该设备内存不足。这是为推力向量释放内存的正确方法吗?我还应该注意,该代码适用于较小的数据量(高达 1.5G)

4

2 回答 2

2

看到一个完整的、可编译的复制器代码会很有用。但是,您可能会遇到内存碎片。

即使大量内存可能被报告为空闲,也可能无法在单个大的连续块中分配它。然后,此碎片将限制您可以请求的单个分配的最大大小。

这可能不是您如何释放内存的真正问题,而更多的是释放内存后剩余的开销分配的函数。您正在检查内存信息并获得大量返回的事实告诉我您正在正确释放分配。

要尝试解决此问题,一种方法是仔细管理和重用您的分配。例如,如果您需要设备float上的大型 2.4G 工作设备向量,则分配一次,然后将其重新用于后续操作。此外,如果您在尝试重新分配 2.4G 向量之前在设备上有任何剩余分配,则在尝试重新分配 2.4G 之前尝试释放这些(即释放您在设备上所做的所有分配)向量。

于 2013-07-26T13:25:56.923 回答
1

当我在搜索相同错误消息/问题的答案时遇到这个问题时,我提供了这个答案。

Robert Crovella 的出色回答当然是正确的,但是,其他人可能知道在创建/请求 a 时分配device_vector容量device_vector远远大于请求的大小device_vector

这个答案:Understanding Thrust (CUDA) memory usage,更详细地解释了为什么 Thrust 会以这种方式运行。

就我而言,在 Ubuntu 16.04、Quadro K1200、CUDA 工具包 8.0 上,请求device_vector大小为 67108864(双倍)的 a 会导致device_vector分配容量大 8 倍(536870912)的 a。

Requested (R) | Capacity (C)  | Total Mem  | Free Mem   | C/Free   | R/C
67108864      | 536870912     | 4238540800 | 3137077248 | 0.171137 | 0.125

上面的输出来自修改我链接到的答案中的一些非常有用的代码。

于 2017-08-12T07:55:25.003 回答