将 T[] 转换为 T[][] 的最快方法?

2023-11-23

So 事实证明并非所有数组都是一样的。多维数组可以具有非零下界。例如,请参阅 Excel PIA 的 Range.Value 属性object[,] rectData = myRange.Value;

我需要将这些数据转换为锯齿状数组。我在下面的第一次尝试有点复杂。有什么优化建议吗?它需要处理下限可能不为零的一般情况。

我有这个前方法:

    public static T[][] AsJagged<T>( this T[,] rect )
    {
        int row1 = rect.GetLowerBound(0);
        int rowN = rect.GetUpperBound(0);
        int col1 = rect.GetLowerBound(1);
        int colN = rect.GetUpperBound(1);

        int height = rowN - row1 + 1;
        int width = colN - col1 + 1;
        T[][] jagged = new T[height][];

        int k = 0;
        int l;
        for ( int i = row1; i < row1 + height; i++ )
        {
            l = 0;
            T[] temp = new T[width];
            for ( int j = col1; j < col1 + width; j++ )
                temp[l++] = rect[i, j];
            jagged[k++] = temp;
        }

        return jagged;
    }

像这样使用:

    public void Foo()
    {
        int[,] iRect1 = { { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 } };
        int[][] iJagged1 = iRect1.AsJagged();

        int[] lengths = { 3, 5 };
        int[] lowerBounds = { 7, 8 };
        int[,] iRect2 = (int[,])Array.CreateInstance(typeof(int), lengths, lowerBounds);
        int[][] iJagged2 = iRect2.AsJagged();

    }

好奇如果Buffer.BlockCopy()会起作用还是更快?

编辑:AsJagged 需要处理引用类型。

编辑:在 AsJagged() 中发现错误。添加int l;并添加了col1 + width到内循环。


前面的视图警告/假设:

  • 你似乎只使用int作为您的数据类型(或者至少看起来可以使用Buffer.BlockCopy这意味着您通常可以使用原始类型)。
  • 对于您显示的测试数据,我认为使用任何理智的方法不会有太大不同。

话虽如此,以下实现(需要专门针对特定的基元类型(此处为int)因为它使用fixed) 比使用内循环的方法快大约 10 倍:

    unsafe public static int[][] AsJagged2(int[,] rect)
    {
        int row1 = rect.GetLowerBound(0);
        int rowN = rect.GetUpperBound(0);
        int col1 = rect.GetLowerBound(1);
        int colN = rect.GetUpperBound(1);

        int height = rowN - row1 + 1;
        int width = colN - col1 + 1;
        int[][] jagged = new int[height][];

        int k = 0;
        for (int i = row1; i < row1 + height; i++)
        {
            int[] temp = new int[width];

            fixed (int *dest = temp, src = &rect[i, col1])
            {
                MoveMemory(dest, src, rowN * sizeof(int));
            }

            jagged[k++] = temp;
        }

        return jagged;
    }

    [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
    unsafe internal static extern void MoveMemory(void* dest, void* src, int length);

使用以下“测试代码”:

    static void Main(string[] args)
    {
        Random rand = new Random();
        int[,] data = new int[100,1000];
        for (int i = 0; i < data.GetLength(0); i++)
        {
            for (int j = 0; j < data.GetLength(1); j++)
            {
                data[i, j] = rand.Next(0, 1000);
            }
        }

        Stopwatch sw = Stopwatch.StartNew();

        for (int i = 0; i < 100; i++)
        {
            int[][] dataJagged = AsJagged(data);
        }

        Console.WriteLine("AsJagged:  " + sw.Elapsed);

        sw = Stopwatch.StartNew();

        for (int i = 0; i < 100; i++)
        {
            int[][] dataJagged2 = AsJagged2(data);
        }

        Console.WriteLine("AsJagged2: " + sw.Elapsed);
    }

Where AsJagged(第一种情况)是你的原始函数,我得到以下输出:

AsJagged:  00:00:00.9504376
AsJagged2: 00:00:00.0860492

所以确实有一种更快的方法,然而,根据测试数据的大小、实际执行此操作的次数以及您允许不安全和 P/Invoke 代码的意愿,您可能不需要它.

话虽如此,我们使用的是大型矩阵double(比如 7000x10000 元素)它确实产生了巨大的差异。

更新:关于使用 Buffer.BlockCopy

我可能会忽略一些Marshal或其他技巧,但我不认为使用Buffer.BlockCopy这里是可能的。这是因为它要求源数组和目标数组都是一个Array.

在我们的示例中,目标是一个数组(例如int[] temp = ...)但来源不是。虽然我们“知道”对于原始类型的二维数组,布局是这样的,每个“行”(即第一维)都是内存中类型的数组,但不存在安全的(如unsafe) 获取该数组的方法,而无需先复制它。所以我们基本上需要使用一个只处理内存而不关心它的实际内容的函数 - 就像MoveMemory。顺便说一句,内部实现Buffer.BlockCopy做了类似的事情。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 T[] 转换为 T[][] 的最快方法? 的相关文章

随机推荐

  • 精简的 JavaScript 代码会提高性能吗?

    我正在做一个AIR应用程序 因此下载时间不会产生巨大影响 组合和缩小所有 JavaScript 文件是否会影响性能 混淆会如何影响性能 缩小通过减少加载时间 即使只是轻微 来提高页面的整体性能 缩小或混淆都不会以任何可感知的量改变执行时间适
  • Java |= 运算符问题[重复]

    这个问题在这里已经有答案了 我需要关于这个奇怪的操作员的帮助 你能向我解释一下这段代码的作用吗 Override public boolean addAll Collection
  • Jenkins Pull Request 构建器忽略带有 ${sha1} 的分支

    我正在尝试设置Jenkins PR 构建器插件在新的拉取请求上点击 github 我已经按照文档进行操作 并尝试了 许多 不同的配置 但我似乎无法克服这一点 忽略 refs heads jenkins testing 因为它与任何配置的 r
  • xargs:以并行模式将标准输出重定向到文件时丢失输出

    我在并行模式下使用 GNU xargs 版本 4 2 2 并且在重定向到文件时似乎确实会丢失输出 当重定向到管道时 它似乎工作正常 以下 shell 命令演示了最小 完整且可验证的示例的问题 我使用生成 2550 个数字xargs将其分成
  • 图像选择器 flutter web 1.9

    在新的 flutter web 1 9 上寻找图像选择器 我找到了一种方法 但小于 1 9 现在已合并 不知道如何实现此目的 尝试使用 dart html 但无法发布 仅在跑步时 看来对于Flutter web 1 10 dev Unive
  • 创建自定义方法安全表达式的最佳方法

    我正在尝试创建自己的方法安全表达式 我想在其中使用 PreFilter and PostFilter注释 在搜索教程和类似问题时 我发现了两种继续进行的方法 第一个是延长DefaultMethodSecurityExpressionHand
  • ./python:加载共享库时出错:libssl.so.1.1:无法打开共享对象文件:没有这样的文件或目录

    我需要在 Ubuntu 16 04 中尝试使用 openssl 1 1 1 的 python 3 7 python 和 openssl 版本都是预发布的 遵循有关如何统计地将 openssl 链接到 python 的说明以前的帖子 我下载了
  • JavaScript 中有哪些稀疏数组的用例?

    在稀疏数组比 常规 对象更好的情况下 您可以有什么可能的编程用途 我所说的稀疏数组是指 arr Initialize arr 0 W arr 1 T arr 3 F console log arr 0 undefined true cons
  • 嵌套期货未执行

    我遇到了一个奇怪的情况 我正在摆弄CompletableFuture当运行以下代码时 我得到了意想不到的结果 public static void main String args CompletableFuture
  • 计算链表中可能循环的节点数

    问题是这样的 它来自 Sedgwick 的优秀 Java 算法 q 3 54 给定一个指向不包含空链接的单链表中节点的链接 即每个节点要么链接到其自身 要么链接到列表中的另一个节点 确定不同节点的数量 而无需修改任何节点 并且使用不超过常量
  • 使用 Plack 处理多个文件上传

    尝试使用 Plack 处理多个文件上传 My form
  • subprocess.popen 和 subprocess.run 有什么区别

    我是新来的subprocess模块和文档让我想知道两者之间有什么区别subprocess popen and subprocess run 该命令的作用有区别吗 是不是只有比较新的一个 使用哪个更好 subprocess run 在Pyth
  • 在 macOS arm64 架构上使用 x86 库和 OpenMP

    我有一台 MacBook M1 并在我的机器上安装了一个针对 x86 Intel 架构编译的库 我有一些使用 OpenMP 的源代码 我想使用 clang 编译器编译我的代码并将我的可执行文件链接到 x86 库 我可以按照说明编译没有 x8
  • Tensorflow:如何创建 Pascal VOC 风格图像

    我正在致力于在 Tensorflow 中实现语义分割网络 并且我正在尝试弄清楚如何在训练期间写出标签的摘要图像 我想以类似的风格对图像进行编码类分割注释用于 Pascal VOC 数据集 例如 假设我有一个网络 其训练批次大小为 1 有 4
  • 如何查找3个或更多连续字符?

    我正在检查密码 这些功能之一是检查输入的密码是否连续重复 我还没有代码 因为我不知道该怎么做 我找到了这个正则表达式匹配两个或多个非连续的相同字符但它只匹配重复的逗号 以下是场景 5236aaa121 重复模式 因为a连续重复3次 2312
  • 在 PHP 中使用 uasort 访问数组键

    如果有一个相当基本的uasortPHP 中的函数如下所示 uasort arr function a b if a gt b return 1 if a lt b return 1 我尝试排序的数组如下所示 1642 gt 1 9314 g
  • 如何在简单适配器中的 imageview 中显示图像?

    我正在从 JSON 数组获取数据 并且可以在文本视图中显示文本 但在显示图像时遇到问题 这是主要活动 public class test extends ListActivity url to make request private st
  • 在 Azure 逻辑应用程序中反序列化 ServiceBus 内容

    我正在尝试读取 Azure 逻辑应用程序中消息的内容正文 但没有取得太大成功 我看到很多建议都说主体是base64编码的 并建议使用以下内容进行解码 json base64ToString triggerBody ContentData T
  • 使用snakeyaml将.yml文件加载到哈希图中(导入junit库)

    我正在尝试将 opencv 的 yml 文件加载到 arrayLists 均值 投影和标签中 我已经创建了这三个数组列表 并尝试将 yml 文件中的元素解析为它们 我发现了SnakeYAML 文档 但是我没有找到正确的方法 我正在尝试使用
  • 将 T[] 转换为 T[][] 的最快方法?

    So 事实证明并非所有数组都是一样的 多维数组可以具有非零下界 例如 请参阅 Excel PIA 的 Range Value 属性object rectData myRange Value 我需要将这些数据转换为锯齿状数组 我在下面的第一次