【问题标题】:Storing 2D Array with Protobuf (C#)使用 Protobuf (C#) 存储二维数组
【发布时间】:2021-01-24 09:49:02
【问题描述】:

我有一个大型多维数组,需要用 protobuf 存储。该数组最多可以包含 5120*5120 = 26,214,400 个项目。不幸的是,Protobuf 不支持存储多维数组。

作为测试,我写了两个函数和一个额外的类。类存储和 x,y 指向数组内部的位置 (array[x, y])。该类有一个“值”,即来自数组 [x,y] 的数据。我使用 List 来存储这些数据。

当我生成一个相当小的数组 (1024*1024) 时,我得到一个超过 169MB 的输出文件。根据我的测试,它加载并生成文件非常快,所以那里没有问题。但是,文件大小很大 - 我肯定需要减小大小。

这是一个正常的文件大小,还是我要重新考虑我的整个过程?我应该在保存之前压缩数据吗(压缩文件需要从 169MB 到 6MB)?如果是这样,用 C# 压缩文件最快/最简单的方法是什么?

这是基于我的真实代码的伪代码。

[ProtoContract]
public class Example
{
    [ProtoIgnore]
    public string[,] MyArray { get; set; }

    [ProtoMember(0)]
    private List<MultiArray> Storage { get; set; }

    public void MoveToList()
    {
        for (int x = 0; x < MyArray.GetLength(0); x++)
        {
            for (int y = 0; y < MyArray.GetLength(1); y++)
            {
                Storage.Add(new MultiArray
                {
                    _x = x,
                    _y = y,
                    value = MyArray[x, y]
                }); 
            }
        }
    }

    public void MoveToArray()
    {
        MyArray = new string[1024, 1024];
        for (int i = 0; i < Storage.Count; i++)
        {
            MyArray[Storage[i].X, Storage[i].Y] = Storage[i]._value;
        }
    }
}

[ProtoContract]

public class MultiArray
{
    [ProtoMember(0)]
    public int _y { get; set; }
    [ProtoMember(1)]
    public int _x { get; set; }
    [ProtoMember(2)]
    public string _value { get; set; }
}

注意:该值必须是数组的正确 x/y。

感谢任何建议。

【问题讨论】:

    标签: c# arrays list protobuf-net


    【解决方案1】:

    我不了解存储,但这可能不是正确的方法。
    您这样做的方式是为数组的每个单元格创建一个 MultiArray 对象。
    一个更简单、更有效的解决方案是这样做:

    String[] Storage = new String[1024*1024];
    int width = 1024
    int height = 1024;
    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < height; y++)
        {
            Storage[x*width+y]=MyArray[x,y];
        }
    }  
    

    【讨论】:

    • 谢谢!今晚我将对此进行试验。
    【解决方案2】:

    最终,protobuf 格式没有比一维更高的数组的概念。

    在库级别,因为您使用的是 protobuf-net,我们可以让库在这里发挥一些作用,基本上将其视为;

    message Array_T {
        repeated int32 dimensions;
        repeated T items; // packed when possible
    }
    

    (注意 .proto 实际上并不支持泛型,但这在库级别并不重要)

    但是,从 x-plat 的角度来看,这会有点尴尬。

    但是为了测试这是否有帮助,您可以线性化您的二维数组,并查看它需要多少空间。

    在您的情况下,我怀疑真正的问题(重新大小)是字符串的数量。 Protobuf 每次都会写入字符串内容,而不会尝试查找表。可能还值得检查一下您的数组内容的 sunlm 字符串总长度(以 UTF-8 字节为单位)是多少。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-14
      • 1970-01-01
      • 2015-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-18
      相关资源
      最近更新 更多