指向结构体向量的指针

问题描述 投票:0回答:1

我有一个自定义结构的 std::vector,其中包含两个 int (并且只有两个 int):

struct S {
    int p0;
    int p1;
};
std::vector<S> v(dimension);

我想要一个指向这个结构体数组的指针,将其解释为原始维度两倍的 int 数组。 上下文如下:struct 的 std::vector (此处为

v
)是在一些遗留代码中构造的。在我自己的代码中,这个数组必须与 GPU 通信(通过 cudaMemcpy)。

第一个解决方案是重新生成一个新的 int 数组,其维度是原始数组的两倍。然后新的 int 数组与 GPU 的通信就很简单了。

但是,我想避免在 CPU 内存上进行此复制,以节省时间和内存使用量。 相反,我希望安全地获得指向结构向量的第一个元素的指针。我可以确定这是安全的吗?我能否确保在阅读

p0
时,
p1
(p0, p1, p0, p1, ...)
字段在内存中与
v
对齐?换句话说,当
*(ptr+2*i)
指向时,我能否确定
*(ptr+2*i+1)
p0
将分别是原始数组
p1
的第 i 个元素的
v
ptr
整数到这个原始数组的顶端?

下面是一个简约的独立说明性示例。从这段代码来看,似乎一切都很顺利。会一直这样吗?

/*
Compilation: nvcc main.cu -o main.cuda
or g++ main.cpp -o main when removing cudaMemcpy's and cudaFree
*/
#include <vector>
#include <cassert>
#include <cuda_runtime.h>

struct S {
    int p0;
    int p1;
};

int main()
{
    assert(sizeof(S)==2*sizeof(int));

    unsigned int n = 10;
    unsigned int dimension = (1UL)<<n; // =2^n

    std::vector<S> v(dimension);
    // initialize array of struct - done in legacy code
    int shift = 10;
    for (int i=0; i<dimension; ++i) {
        v[i].p0 = shift+2*i;
        v[i].p1 = shift+2*i+1;
    }

    int *d_v;
    cudaMalloc((void**)&d_v, 2*dimension*sizeof(int));

    // solution 1 - to be avoided - re-allocate the array on CPU memory and copy values to GPU
    std::vector<int> v2(2*dimension);
    for (int i=0; i<dimension; ++i) {
        v2[2*i] = v[i].p0;
        v2[2*i+1] = v[i].p1;
    }
    cudaMemcpy(d_v, v2.data(), 2*dimension, cudaMemcpyHostToDevice);

    // solution 2 (?)
    int * ptr = (int*)v.data(); // safe ?
    // ptr should point to the "p0" field of the first element of v. Let's check:
    for (int i=0; i<2*dimension; ++i) {
        assert( *(ptr+i) == shift+i ); // Ok. Is it always true ?
    }
    cudaMemcpy(d_v, ptr, 2*dimension, cudaMemcpyHostToDevice); // Is it fully safe ?

    /* ... use d_v in Cuda kernels */

    cudaFree(d_v);

    return 0;
}
c++ cuda
1个回答
0
投票

你问:

换句话说,我能否确定

*(ptr+2*i)
*(ptr+2*i+1)
将分别是原始数组
p0
的第i个元素的
p1
v
整数,当
ptr
时指向这个原始数组的尖端?

严格来说,我无法在语言中找到任何可以保证这一点的内容。

如果您能够验证

sizeof(S)
等于
2*sizeof(int)
,我看不出有任何理由不成立。

即,在代码中插入以下行应该足以保证您的代码不会不当使用内存。

static_assert(sizeof(S) == 2*sizeof(int), "Objects are not aligned properly");
© www.soinside.com 2019 - 2024. All rights reserved.