提问人:rocksNwaves 提问时间:6/30/2023 最后编辑:rocksNwaves 更新时间:6/30/2023 访问量:94
'std::vector' 的迭代器构造函数是否复制数据?
Does `std::vector`'s iterator constructor copy the data?
问:
在函数调用中,我有一个动态分配的数组,我想用它来填充向量。这里的上下文是,我知道我无法返回指针,因为它在返回后超出了范围。
我的问题是关于在构造向量后调用创建的指针的安全性。向量是拥有指针的所有权,并因此负责销毁,还是只是复制它的数据?我担心的是,如果我调用并且向量的基础数组与原始数组是相同的内存,那么我将提前销毁其内容。free
free
__host__
std::vector<float> mult(std::vector<float> x, float scalar) {
int n = x.size();
int n_threads = 256;
int n_blocks = (int)ceil(n / n_threads);
size_t bytes = n * sizeof(float);
float *d_x; // gpu "device" inputs
float *d_y; // gpu "device" outputs
float *h_y; // cpu "host" outputs
h_y = (float *)malloc(n * sizeof(float));
cudaMalloc(&d_x, bytes);
cudaMalloc(&d_y, bytes);
cudaMemcpy(d_x, x.data(), bytes, cudaMemcpyHostToDevice);
mult<<<n_blocks, n_threads>>>(n, d_x, scalar, d_y);
cudaMemcpy(h_y, d_y, bytes, cudaMemcpyDeviceToHost);
cudaFree(d_x);
cudaFree(d_y);
std::vector<float> y(h_y, h_y + sizeof(h_y));
free(h_y); <<<< CALL IN QUESTION
return y;
}
文档说:
(3)range构造函数构造一个包含与以下元素一样多的容器 范围 [first,last),每个元素都从其 该范围内的相应元素,顺序相同。
我在谷歌上搜索了“emplace constructed”,但没有找到这个术语的定义,但我觉得这是我问题的关键。
答:
0赞
Martin York
6/30/2023
#1
有趣的是:
// Step 1: Allocate memory.
float *h_y; // cpu "host" outputs
h_y = (float *)malloc(n * sizeof(float));
// Step 2: Copy data from source into allocated memory
cudaMemcpy(h_y, d_y, bytes, cudaMemcpyDeviceToHost);
// Step 3: Copy data from allocated memory to vector
// With a bug.
std::vector<float> y(h_y, h_y + sizeof(h_y));
// Step 4: Free Allocated memory.
free(h_y);
您的初始问题?“Step 4: free(h_y)”是否弄乱了向量内存。
简短的回答:不。
长答案:容器(如 vector)管理自己的内存。因此,它会分配空间并将数据复制到此内存中。所以你应该释放这个内存。
但是:你有一个错误:
std::vector<float> y(h_y, h_y + sizeof(h_y));
// sizeof(h_y) is the size of the pointer (probably 8 bytes)
// Not the size of the allocated memory.
// So you have only copyied one or two floats into the vector.
您可能想要:
std::vector<float> y(h_y, h_y + n);
Emplace 构造:
这只是一种奇特的说法,我们将避免调用默认构造函数,然后调用复制构造函数。相反,它将通过调用构造函数传递对范围中每个项的引用来确保向量中的对象是“就地”构造的。
由于您没有实际的构造函数,因此只需将范围中的每个值直接复制到分配的向量内存中即可。float
你应该做什么:
不要分配临时缓冲区。只需确保向量具有足够的大小,然后直接从 CUDA 复制到您的向量中即可。
// Step 1: Allocate memory (in the vector)
std::vector<float> y(n);
// Step 2: Copy data from source into allocated memory
cudaMemcpy(&y[0], d_y, bytes, cudaMemcpyDeviceToHost);
// Note: &y[0] is the address of the first element in the vector.
// vectors are contiguous.
评论
vector
管理自己的内存,这就是推荐它的原因。 将缓冲区复制到 Vecotr 中。std::vector<float> y(h_y, h_y + sizeof(h_y));
vector
管理它自己的内存。当您创建一个内存时,它会分配自己的内存并对其进行处理。malloc
free
cudaMemcpy
std::vector<float> y(n); cudaMemcpy(y.data(), d_y, bytes, cudaMemcpyDeviceToHost);
h_y + sizeof(h_y)
h_y
是指向数组的指针,而不是数组。 是指针的大小,与要复制的范围的大小无关。您需要添加实际的元素数才能获得“结束”指针(大概)。sizeof(h_y)
h_y
n
std::vector