加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

通过C和/或程序集帮助优化C#函数

发布时间:2020-12-16 05:52:07 所属栏目:百科 来源:网络整理
导读:我有这个我想要优化的C#方法: // assume arrays are same dimensionsprivate void DoSomething(int[] bigArray1,int[] bigArray2){ int data1; byte A1,B1,C1,D1; int data2; byte A2,B2,C2,D2; for (int i = 0; i bigArray1.Length; i++) { data1 = bigArr
我有这个我想要优化的C#方法:
// assume arrays are same dimensions
private void DoSomething(int[] bigArray1,int[] bigArray2)
{
    int data1;
    byte A1,B1,C1,D1;
    int data2;
    byte A2,B2,C2,D2;
    for (int i = 0; i < bigArray1.Length; i++)
    {
        data1 = bigArray1[i];
        data2 = bigArray2[i];

        A1 = (byte)(data1 >> 0);
        B1 = (byte)(data1 >> 8);
        C1 = (byte)(data1 >> 16);
        D1 = (byte)(data1 >> 24);

        A2 = (byte)(data2 >> 0);
        B2 = (byte)(data2 >> 8);
        C2 = (byte)(data2 >> 16);
        D2 = (byte)(data2 >> 24);

        A1 = A1 > A2 ? A1 : A2;
        B1 = B1 > B2 ? B1 : B2;
        C1 = C1 > C2 ? C1 : C2;
        D1 = D1 > D2 ? D1 : D2;

        bigArray1[i] = (A1 << 0) | (B1 << 8) | (C1 << 16) | (D1 << 24); 
    }
}

该函数基本上比较了两个int数组.对于每对匹配元素,该方法对每个单独的字节值进行比较,并取得两者中较大者.然后,第一个数组中的元素被分配一个从4个最大字节值构造的新的int值(不考虑源).

我想我已经在C#中尽可能的优化了这个方法(当然我也没有,对这个分数的建议也是可以接受的).我的问题是,是否值得我将此方法转移到非托管C DLL?考虑到编组我的托管int数组的开销,所得到的方法执行速度会更快(并且速度更快),以便将它们传递给方法?

如果这样做会让我,比如提高10%的速度,那么我的时间肯定不值得.如果速度是2或3倍,那么我可能要这样做.

注意:请不要“过早优化”评论,提前感谢.这只是“优化”.

更新:我意识到我的代码示例没有捕获我在这个函数中尝试做的一切,所以这里是一个更新的版本:

private void DoSomethingElse(int[] dest,int[] src,double pos,double srcMultiplier)
{
    int rdr;
    byte destA,destB,destC,destD;
    double rem = pos - Math.Floor(pos);
    double recipRem = 1.0 - rem;
    byte srcA1,srcA2,srcB1,srcB2,srcC1,srcC2,srcD1,srcD2;
    for (int i = 0; i < src.Length; i++)
    {
        // get destination values
        rdr = dest[(int)pos + i];
        destA = (byte)(rdr >> 0);
        destB = (byte)(rdr >> 8);
        destC = (byte)(rdr >> 16);
        destD = (byte)(rdr >> 24);
        // get bracketing source values
        rdr = src[i];
        srcA1 = (byte)(rdr >> 0);
        srcB1 = (byte)(rdr >> 8);
        srcC1 = (byte)(rdr >> 16);
        srcD1 = (byte)(rdr >> 24);
        rdr = src[i + 1];
        srcA2 = (byte)(rdr >> 0);
        srcB2 = (byte)(rdr >> 8);
        srcC2 = (byte)(rdr >> 16);
        srcD2 = (byte)(rdr >> 24);
        // interpolate (simple linear) and multiply
        srcA1 = (byte)(((double)srcA1 * recipRem) + 
            ((double)srcA2 * rem) * srcMultiplier);
        srcB1 = (byte)(((double)srcB1 * recipRem) +
            ((double)srcB2 * rem) * srcMultiplier);
        srcC1 = (byte)(((double)srcC1 * recipRem) +
            ((double)srcC2 * rem) * srcMultiplier);
        srcD1 = (byte)(((double)srcD1 * recipRem) +
            ((double)srcD2 * rem) * srcMultiplier);
        // bytewise best-of
        destA = srcA1 > destA ? srcA1 : destA;
        destB = srcB1 > destB ? srcB1 : destB;
        destC = srcC1 > destC ? srcC1 : destC;
        destD = srcD1 > destD ? srcD1 : destD;
        // convert bytes back to int
        dest[i] = (destA << 0) | (destB << 8) |
            (destC << 16) | (destD << 24);
    }
}

本质上这与第一种方法是一样的,除了在第一种方法之外,第二个数组(src)总是小于第一个(dest),而第二个数组相对于第一个数组(即不是位于,比如说相对于dest,10可以定位在10.682791).

为了实现这一点,我必须在源中的两个包围值之间进行内插(例如,在上面的例子中为10和11,对于第一个元素),然后将插入的字节与目标字节进行比较.

我怀疑这个函数所涉及的乘法比字节比较成本要高得多,所以这部分可能是一个红色的鲱鱼(对不起).此外,即使比较相对于乘法仍然有些昂贵,我仍然有这个问题,即该系统实际上可以是多维的,这意味着不是比较一维阵列,阵列可以是2-,5-或所以最终计算内插值所花费的时间将缩短4个字节的最后一个字节比较所花费的时间(我假设是这种情况).

这里的乘法相对于位移有多贵,而且这种操作可以通过卸载到C DLL(甚至是一个程序集DLL)来加速,尽管我必须聘请有人来创建为了我)?

解决方法

下面的函数使用不安全的代码来将整数数组视为字节数组,这样就不需要加倍位了.
private static void DoOtherThing(int[] bigArray1,int[] bigArray2)
    {
        unsafe
        {
            fixed (int* p1 = bigArray1,p2=bigArray2)
            {
                byte* b1 = (byte*)p1;
                byte* b2 = (byte*)p2;
                byte* bend = (byte*)(&p1[bigArray1.Length]);
                while (b1 < bend)
                {
                    if (*b1 < *b2)
                    {
                        *b1 = *b2;
                    }
                    ++b1;
                    ++b2;
                }
            }
        }
    }

在我的机器上,在版本模式下运行的调试器与2500万个int数组相比,这个代码比原来的快29%.但是,独立运行时,运行时几乎没有区别.有时你的原始代码更快,有时新的代码更快.

大概数字:

Debugger  Standalone
Original  1,400 ms    700 ms
My code     975 ms    700 ms

而且,是的,我做了比较结果,以确保功能做同样的事情.

我很遗憾的解释为什么我的代码不是更快,因为它的工作明显减少了.

鉴于这些结果,我怀疑您可以通过转到本地代码来改善事情.正如你所说,编组阵列的开销可能会减少您在处理中可能会实现的任何节省.

然而,对原始代码的以下修改速度比10%至20%更快.

private static void DoSomething(int[] bigArray1,int[] bigArray2)
    {
        for (int i = 0; i < bigArray1.Length; i++)
        {
            var data1 = (uint)bigArray1[i];
            var data2 = (uint)bigArray2[i];

            var A1 = data1 & 0xff;
            var B1 = data1 & 0xff00;
            var C1 = data1 & 0xff0000;
            var D1 = data1 & 0xff000000;

            var A2 = data2 & 0xff;
            var B2 = data2 & 0xff00;
            var C2 = data2 & 0xff0000;
            var D2 = data2 & 0xff000000;

            if (A2 > A1) A1 = A2;
            if (B2 > B1) B1 = B2;
            if (C2 > C1) C1 = C2;
            if (D2 > D1) D1 = D2;

            bigArray1[i] = (int)(A1 | B1 | C1 | D1);
        }
    }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读