我有一个工作流程如下:
- 加载初始值
- 将值处理为中间结果 A
- 过程 A 到中间结果 B
- 过程 B 到中间结果 C
- 过程 C 和 B 到中间结果 D 和 E
- 将部分 D 与最终结果 F 相加
我所有中间结果的自然结构是一个二维数组,我使用 cudaMallocPitch() 分配它。
不幸的是,我的算法要求我同时将 D、E、C 和 B 保存在内存中,并且 D 和 E 在内存中分别比 B 大 4 倍。由于我的处理中的另一个限制(迭代图结构在内存中),A或B的维度受D和E的最大维度的限制,这又由初始值的内存使用量+ B的内存消耗+ C的内存消耗决定。这种依赖性是因为我正在从主机向/从设备内存“分页”中间结果的部分(以适应非常大的问题集),并且在整个步骤 1-3 完成之前我无法开始步骤 4问题集。
一旦我有整个问题集的 B,我就可以删除 A。
我目前正在使用以下函数确定 D+E 的最大大小:
int gpuCalculateSimulPatterns(int lines, int patterns) {
// get free memory
size_t free_mem, total_mem;
int allowed_patterns;
cudaMemGetInfo(&free_mem, &total_mem);
allowed_patterns = (free_mem - (lines*sizeof(int))) / (lines*(sizeof(int)*2.5) + lines*sizeof(char)*1.5);
return min(patterns, allowed_patterns -(allowed_patterns % 32));
}
它“有效”,但只是因为我高估了 D 或 E 的大小(它们的尺寸和内存使用量相同) 25% 并将 B 的预期大小翻了一番。即便如此,我仍然会遇到我的记忆的边缘情况分配失败,因为它的内存不足。我想更有效地利用卡上的内存并保持对齐,因为我的内核对全局内存进行了多次读写。
不,使用共享内存不是一种选择,因为我在多个块中使用多个内核,并且块内的线程根本不交互。
我发现 cudaMallocPitch() 只返回已成功分配的内存的使用音高。有没有办法向驱动程序提交 2D 内存分配请求,然后只询问它分配的间距?
我会安装一个试错优化例程,但是 A、B、D 和 E 之间的尺寸关联依赖性(CI 计算先验,因为它没有分配音高线性)使得这是一个糟糕的解决方案,它需要为每个问题集重新计算。
有没有人有更好的方法可以让我确定适合任意数量设备内存的中间数据集的适当大小?
编辑:
中间 A 的内存正在被重用,我的边界计算假设 C+D+E+B >> Initial + A + B (由于 A 和 B 是相同的尺寸,而 C、D、E 是整数),因此我只需要确保 B + C + D + E 有足够的空间。
我只使用 Compute Capability 2.x 卡来测试(Quadro 2000、Tesla C2075、GTX460)。