我在Matlab中有一个多维矩阵,我将其保存为二进制文件,如下所示:
mat = reshape(1:90, 9,5,2);
fileName = 'mat.bin';
fid = fopen(fileName, 'w');
fwrite(fid, mat, 'int32');
fclose(fid);
在C ++中,我像这样加载它:
struct Mat {
int32_t arr[9][5][2];
};
std:ifstream input("mat.bin");
Mat* m = new Mat();
input.read(reinterpret_cast<char*>(m), sizeof(Mat));
input.close();
问题是,例如,装入的数据在内存中的排列方式不同:
访问arr[1][1][1]
将产生Matlab索引数组的值mat(5,2,1)
(当然要考虑Matlab的索引从1开始)
在将矩阵(和任何其他多维矩阵)写入二进制文件之前,该如何将其布置arr[i][j][k]
为与mat(i+1, j+1, k+1)
?
编辑:
当前解决方案
对于2D情况,矩阵转置可解决该问题。对于xD,我发现我可以像这样改变向量的顺序,
permute(mat, [D D-1 D-2 ... 1])
就像散布向量(这与在C ++中映射内存的方式一样),我仍然在寻找更通用的代码,而不必编写尺寸向量(有时会改变)
谢谢。
始终最好将数组存储为纯1D数组并固定访问方式。您mat[5][2][1]
等于mat[1 + 2*2 + 5*10]
。在进行动态内存分配时,创建索引为索引mat[5][2][1]
的数组意味着将指针数组分配给数据数组的指针。这在内存分配中涉及巨大的开销(这是非常昂贵的),并导致内存碎片和较差的缓存性能。相反,分配一个可以保存数据的普通数组,然后从3个索引中计算线性索引是非常简单且便宜的。
这是动态分配的3D数组的简单实现(不进行任何形式的检查):
struct Mat {
using value_type = int32_t;
std::vector<value_type> data;
int size[3] = {0, 0, 0};
Mat(int s1, int s2, int s3) {
size[0] = s1; size[1] = s2; size[2] = s3;
data.resize(s1 * s2 * s3);
}
value_type operator()(int i, int j, int k) {
return data[(k * size[1] + j) * size[0] + i];
}
};
当然,您可以将其class
隐藏成适当的数据,等等。或者您可以只使用存在的实现此类数组的众多库之一。有一个()
用于索引的重载运算符:m(5,2,1)
转换为适当的索引到1D array中m.data
。(在这里,我没有费心通过引用返回索引元素,但这当然更有意义)。
这是测试它的完整程序。输入数据按主要列存储顺序为整数1:90,在MATLAB中,我看到以下内容:
>> mat(6,3,2)
ans = 69
C ++程序输出以下内容:
m(5,2,1) = 69
源代码:
#include <vector>
#include <fstream>
#include <iostream>
struct Mat {
using value_type = int32_t;
std::vector<value_type> data;
int size[3] = {0, 0, 0};
Mat(int s1, int s2, int s3) {
size[0] = s1; size[1] = s2; size[2] = s3;
data.resize(s1 * s2 * s3);
}
value_type operator()(int i, int j, int k) {
return data[(k * size[1] + j) * size[0] + i];
}
};
int main() {
std::ifstream input("mat.bin");
Mat m(9, 5, 2);
input.read(reinterpret_cast<char*>(m.data.data()), m.data.size() * sizeof(Mat::value_type));
input.close();
std::cout << "m(5,2,1) = " << m(5,2,1) << '\n';
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句