我有一个C++类容器,它分配普通对象的1GB内存(例如内置内存)。
我需要将部分对象复制到GPU。为了加速和简化传输,我想将CPU内存注册为不可分页(“固定”),例如在复制之前使用cudaHostRegister(void*, size, ...)
。
(这似乎是用最小逻辑复制内存进一步子集的好方法。例如,如果简单的cudaMemcpy是不够的。)
是否安全地传递指向原始分配内存的 part 的指针,例如,原始1GB.的一个连续的100 1GB子集。
我可能只想注册部分是因为效率,但也是因为在调用跟踪的深处,我可能丢失了原始分配指针的信息。
换句话说,指向cudaHostRegister
的指针参数可以是分配的指针以外的其他东西吗?特别是从分配的内存导出的算术结果,但仍在分配的范围内。
它似乎有效,但我不明白,一般来说,“固定”分配的一部分是否会以某种方式破坏分配块。
更新:我担心的是分配实际上是在documentation for the cudaHostRegister
flag options中提到的
的内存。
获得指向内存的设备指针。
。
中的cudaHostRegister出错。
发布于 2021-10-09 10:00:49
是否可以安全地传递一个指针,该指针仅指向原始分配内存的一部分,例如,原始1GB的一个相邻的100 1GB子集。
虽然我同意文件可能更清楚,但我认为问题的答案是“是”。
原因如下:另一种解释是,只有由malloc
返回的整个内存段才允许注册。但是,这是不可行的,因为malloc
可以在幕后分配一个大的部分,并且只分配给用户部分。因此,即使您(用户)在cudaHostRegister
中使用malloc
返回的那些部分,它们实际上也是以前分配的更大内存块的片段。
顺便说一句,Linux有一个类似的内核调用来锁定名为mlock
的内存。它接受任意内存范围。
其他答案之一声称(直到这一测试发布):
如果您只需要将对象的一部分复制到GPU,那么使用
()是没有用的,因为它很可能会将数据从物理上复制到其他地方,这样就不会保存任何东西了。
但这是不正确的:注册是值得的,如果要复制的内存块足够大,即使只复制一次。我看到这个代码的速度提高了大约2倍(注释掉了所指示的行),或者如果在计时器之间也做了注销的话,大约是50%。
#include <chrono>
#include <iostream>
#include <vector>
#include <cuda_runtime_api.h>
int main()
{
std::size_t giga = 1024*1024*1024;
std::vector<char> src(giga, 3);
char* dst = 0;
if(cudaMalloc((void**)&dst, giga)) return 1;
cudaDeviceSynchronize();
auto t0 = std::chrono::system_clock::now();
if(cudaHostRegister(src.data() + src.size()/2, giga/8, cudaHostRegisterDefault)) return 1; // comment out this line
if(cudaMemcpy(dst, src.data() + src.size()/2, giga/8, cudaMemcpyHostToDevice)) return 1;
cudaDeviceSynchronize();
auto t1 = std::chrono::system_clock::now();
auto d = std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count();
std::cout << (d / 1e6) << " seconds" << std::endl;
// un-register and free
}
发布于 2021-10-09 09:30:17
这是一个经验之谈,而不是一个恰当的答案:
当数据自动化系统的文档不能保证某件东西能正常工作时,你就需要假设它不起作用。因为如果它确实有效--对你来说,现在,在你所拥有的系统上--它可能会在将来停止工作;或者在另一个系统上,或者在另一个使用场景中。
更具体地说,内存钉扎是在页面分辨率上进行的,所以除非您想要的部分开始并结束在物理页面边界上,否则CUDA驱动程序将需要在您所要求的区域之前和之后插入更多的内存--这是它可以做到的,但它需要多走一英里才能满足您的需要,我怀疑如果没有文档,这种情况是否会发生。
我还建议您通过developer.nvidia.com提交错误报告,要求它们在文档中澄清这一点。我的经验是.大约有50%的几率他们会对这样的错误报告做些什么。
最后-你可以试一试:编写一个程序,复制到GPU与和不固定的部分区域,看看是否有吞吐量的差异。
https://stackoverflow.com/questions/69498286
复制相似问题