对于使用Tensorflow的C API的项目,我必须将void指针(void *)传递给Tensorflow的方法。在示例中,void *指向2d数组,这对我也有用。但是现在我的数组尺寸不允许我使用堆栈,这就是为什么我必须使用动态数组或向量的原因。
我设法用相同的条目创建一个动态数组:
float** normalizedInputs;//
normalizedInputs = new float* [noCellsPatches];
for(int i = 0; i < noCellsPatches; ++i)
{
normalizedInputs[i] = new float[no_input_sizes];
}
for(int i=0;i<noCellsPatches;i++)
{
for(int j=0;j<no_input_sizes;j++)
{
normalizedInputs[i][j]=inVals.at(no_input_sizes*i+j);
////
////
//normalizedInputs[i][j]=(inVals.at(no_input_sizes*i+j)-inputMeanValues.at(j))/inputVarValues.at(j);
}
}
需要void *的函数调用如下:
TF_Tensor* input_value = TF_NewTensor(TF_FLOAT,in_dims_arr,2,normalizedInputs,num_bytes_in,&Deallocator, 0);
在参数4中,您会看到“ normalizedInputs”数组。现在运行程序时,计算结果完全错误。当我回到静态数组时,它们又正确了。我必须更改什么?
致敬,谢谢!
编辑:我还注意到,TF_Tensor* input_value
在两种情况下都具有完全不同的值(对于动态情况,它具有许多0和nan条目)。有没有一种方法可以通过使用std::vector<std::vector<float>>
来解决?
分别:是否有任何有效方法将连续的动态2d数据结构传递给void *的函数?
答案 0 :(得分:1)
在参数4中,您会看到“ normalizedInputs”数组。现在运行程序时,计算结果完全错误。
之所以不起作用,是因为您将指针数组作为数据传递。在这种情况下,您将必须使用normalizedInputs[0]
或等效的更明确的表达式&normalizedInputs[0][0]
。但是,此代码还有另一个更大的问题。
由于在循环内使用new
,因此不会有TF_NewTensor
期望的连续数据。有几种解决方法。
如果您确实需要2D阵列,则可以通过两种分配来解决。一种用于指针,另一种用于数据。然后将指针适当地设置到数据数组中。
float **normalizedInputs = new float* [noCellsPatches]; // allocate pointers
normalizedInputs[0] = new float [noCellsPatches*no_input_sizes]; // allocate data
// set pointers
for (int i = 1; i < noCellsPatches; ++i) {
normalizedInputs[i] = &normalizedInputs[i-1][no_input_sizes];
}
然后,您可以像往常一样在C ++中使用normalizedInputs[i][j]
,并在normalizedInputs[0]
调用中使用&normalizedInputs[0][0]
或TF_NewTensor
表达式。
这是一种机械上更简单的解决方案,只需使用平面一维阵列即可。
float * normalizedInputs = new float [noCellsPatches*no_input_sizes];
您可以通过i,j
访问第normalizedInputs[i*no_input_sizes+j]
个元素,并且可以直接在TF_NewTensor
调用中使用它,而不必担心任何地址。
答案 1 :(得分:1)
C ++标准尽其所能防止程序员使用原始数组,特别是多维数组。
根据您的评论,您静态声明的数组被声明为:
float normalizedInputs[noCellsPatches][no_input_sizes];
如果noCellsPatches
和no_input_sizes
都是编译时间常数,则您有正确的程序声明了真正的2D数组。如果它们不是常量,则说明正在声明2D可变长度数组...,它在C ++标准中不存在。幸运的是,gcc允许它作为扩展,但不允许MSVC或clang。
如果要声明具有非恒定行和列的动态2D数组并使用gcc,则可以执行以下操作:
int (*arr0)[cols] = (int (*) [cols]) new int [rows*cols];
(天真int (*arr0)[cols] = new int [rows][cols];
被我的gcc 5.4.0拒绝了)
这绝对不是正确的C ++,但已被gcc接受并且可以完成预期的工作。
诀窍在于,我们都知道大小为n的数组的大小以一个元素的大小的n倍为单位。 rows
行的columns
行的2D数组,如果rows
乘以一行的大小,则在基础元素(此处为columns
中进行测量时即为int
)。因此,我们要求gcc分配一个2D数组大小的1D数组,并采用严格的别名规则获取足够的自由度,以将其作为所需的2D数组进行处理。如前所述,它违反了严格的别名规则,并在C ++中使用VLA,但gcc接受它。