寻找信息来提高代码速度

Gra*_*ant 6 c# optimization performance

我有一些代码可以从720p和24fps的摄像头流式传输视频.我试图在代码中捕获这个流,并最终通过将压缩的jpegs放在mjpeg等中来创建它的视频.我遇到的问题是这个整体代码不够快,无法以每帧24 fps或.04秒的速度创建.

运用

Stopwatch();
Run Code Online (Sandbox Code Playgroud)

我发现循环的内部每个循环需要.000000000022秒.

每个循环完成循环的外部需要.0000077秒.

我发现从开始到图像保存的整个功能每次运行运行.21秒.

从内部循环计算完成图像:

.000000000022 x 640 = .000000001408 seconds
.000000001408 x 360 = .00000050688  seconds
Run Code Online (Sandbox Code Playgroud)

从外部循环计算到完成图像:

.0000077 x 360 = .002772 seconds
Run Code Online (Sandbox Code Playgroud)

如果我可以创建一个与我将被设置的时间相关的图像,但运行整个代码的代码需要.21秒来完成所有代码

temp_byte1 = main_byte1;
temp_byte2 = main_byte2;

timer1.Reset();
timer1.Start();

Bitmap mybmp = new Bitmap(1280, 720);
BitmapData BPD = mybmp.LockBits(new Rectangle(0, 0, 1280, 720), ImageLockMode.WriteOnly, mybmp.PixelFormat);
IntPtr xptr = BPD.Scan0;
IntPtr yptr = BPD.Scan0;
yptr = new IntPtr( yptr.ToInt64() + (1280 * 720 * 2));
int bytes = Math.Abs(BPD.Stride);
byte[][] rgb = new byte[720][];
int Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8;
int U1, U2, V1, V2, U3, U4, V3, V4;
for (int one = 0; one < 360; one++)
{
    timer2.Reset();
    timer2.Start();
    rgb[one] = new byte[bytes];
    rgb[360 + one] = new byte[bytes];
    for (int two = 0; two < 640; two++)
    {
        timer3.Reset();
        timer3.Start();
        U1 = temp_byte1[one * 2560 + 4 * two + 0];
        Y1 = temp_byte1[one * 2560 + 4 * two + 1];
        V1 = temp_byte1[one * 2560 + 4 * two + 2];
        Y2 = temp_byte1[one * 2560 + 4 * two + 3];

        U2 = temp_byte2[one * 2560 + 4 * two + 0];
        Y3 = temp_byte2[one * 2560 + 4 * two + 1];
        V2 = temp_byte2[one * 2560 + 4 * two + 2];
        Y4 = temp_byte2[one * 2560 + 4 * two + 3];

        RGB_Conversion(Y1, U1, V1, two * 8 + 0, rgb[one]);
        RGB_Conversion(Y2, U1, V1, two * 8 + 4, rgb[one]);

        RGB_Conversion(Y3, U2, V2, two * 8 + 0, rgb[(360 + one)]);
        RGB_Conversion(Y4, U2, V2, two * 8 + 4, rgb[(360 + one)]);

        timer3.Stop();
        timer3_[two] = timer3.Elapsed;
    }
    Marshal.Copy(rgb[one], 0, xptr, 5120);
    xptr = new IntPtr(xptr.ToInt64() + 5120);
    Marshal.Copy(rgb[(360 + one)], 0, yptr, 5120);
    yptr = new IntPtr(yptr.ToInt64() + 5120);
    timer2.Stop();
    timer2_[one] = timer2.Elapsed;
}
mybmp.UnlockBits(BPD);
mybmp.Save(GetDateTimeString("IP Pictures") + ".jpg", ImageFormat.Jpeg);
Run Code Online (Sandbox Code Playgroud)

代码工作,它将yuv422传入的字节数组转换为完整大小的jpeg,但无法理解为什么for循环的速度和整个代码之间存在这样的差异

我感动了

byte[][]rgb = new byte[720];  
rgb[x] = new byte[bytes]; 
Run Code Online (Sandbox Code Playgroud)

在程序启动时获取init而不是每个函数调用/运行没有可测量的速度增加的全局.

UPDATE

RGB转换:接收YUV并将其转换为RGB并将其放入保存值的全局数组中

public void RGB_Conversion(int Y, int U, int V, int MULT, byte[] rgb)
{

    int C,D,E;
    int R,G,B;

    // create the params for rgb conversion
    C = Y - 16;
    D = U - 128;
    E = V - 128;

    //R = clamp((298 x C + 409 x E + 128)>>8)
    //G = clamp((298 x C - 100 x D - 208 x E + 128)>>8)
    //B = clamp((298 x C + 516 x D + 128)>>8)

    R = (298 * C + 409 * E + 128)/256;
    G = (298 * C - 100 * D - 208 * E + 128)/256;
    B = (298 * C + 516 * D + 128)/256;

    if (R > 255)
        R = 255;
    if (R < 0)
        R = 0;
    if (G > 255)
        G = 255;
    if (G < 0)
        G = 0;
    if (B > 255)
        B = 255;
    if (B < 0)
        B = 0;

    rgb[MULT + 3] = 255;
    rgb[MULT + 0] = (byte)B;
    rgb[MULT + 1] = (byte)G;
    rgb[MULT + 2] = (byte)R;
    }
Run Code Online (Sandbox Code Playgroud)

seh*_*ehe 3

首先

需要从循环内部删除Start/Stop和秒表业务

在紧密循环中重置秒表 640x 会导致数字出现偏差。最好使用分析器或测量粗粒度的性能。

此外,这些语句的存在可能会阻止编译器优化(循环平铺和循环展开在这里看起来是非常好的候选者,但 JITter 可能无法使用它们,因为寄存器会被破坏以调用秒表函数......

数据结构:

我有一种感觉,您应该能够使用“平面”数据结构,而不是更新那里的所有锯齿状数组。也就是说,我不知道你将其输入哪个 API,而且我也没有对此进行太多关注。

我确实认为RGB_Conversion”返回 RGB 部分而不是让它写入数组可能确实会给编译器带来优化的优势。

其他想法:

  • 查看RGB_Conversion(它在哪里/如何定义?)。也许你可以将其内联。

  • 使用unchecked来防止所有数组索引操作以检查溢出

  • 考虑使用 /unsafe 代码(此处)以避免边界检查