在不安全的 C# 中使用指针数组

9
在C语言中,我可以这样定义一个指向数组的指针:
char b1[SOME_SIZE];
char (*b3)[3]=(char(*)[3])b1;

因此,b3 [i] [j] == b1 [i * 3 + j]

我能在unsafe C#中声明这样的指针b3吗?

我的意图是访问位图通道,如下所示:

///...
unsafe {
    //...
    byte *target; //8bpp
    byte (*source)[3]; //24bpp
    //...
    target[x]=(source[x][0]+source[x][1]+source[x][2])/3;
    //...

我希望这样做,使用source[x][ch]代替source[x*3+ch]来获得一些编译器优化。

基于Hope的优化实际上没有任何意义。你可以创建一个指针byte*[],但这可能不是你想要的 - 请查看文档 - BartoszKP
@BartoszKP 也许你是对的,我可能过度优化了!我的观点是,在 C/C++ 中,良好的声明通常比繁重的代码具有更好的性能(和可读性),因为编译器可以优化前者而不能优化后者。 - LS_ᴅᴇᴠ
在C#中,这种方法是性能方面处理位图的推荐方式。 - BartoszKP
我知道,但我试图使用指向数组的指针来获得更清晰的代码。 - LS_ᴅᴇᴠ
3
在你的问题中,你说你想要“进行一些编译器优化”,而不是“让代码更清晰”。请明确你的意图,两者不能兼得。 - BartoszKP
只是一个建议,在C#中避免使用不安全的代码。如果这种优化绝对必要,那么可以这样做,但大多数情况下,您可以通过使用System.Runtime.InteropServices中的Marshal类来避免访问非托管代码/指针。 - Erik
1个回答

6
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct FastPixel
{
    public readonly byte R;
    public readonly byte G;
    public readonly byte B;
}


private static void Main()
{
    unsafe
    {
        // 8-bit.
        byte[] b1 =
        {
            0x1, 0x2, 0x3,
            0x6, 0x7, 0x8,
            0x12, 0x13, 0x14
        };


        fixed (byte* buffer = b1)
        {
            var fastPixel = (FastPixel*) buffer;
            var pixelSize = Marshal.SizeOf(typeof (FastPixel));

            var bufferLength = b1.Length / pixelSize;
            for (var i = 0; i < bufferLength; i++)
            {
                Console.WriteLine("AVERAGE {0}", (fastPixel[i].R + fastPixel[i].G + fastPixel[i].B)/pixelSize);
            }
        }
    }
}

这应该与你所拥有的几乎相同。请注意,我不希望获得任何性能上的收益。这不是微观优化,而是纳米级优化。

如果处理大型图像,请研究并行编程和SSE以及缓存行的工作方式(它们实际上节省了我3-4秒 - 真疯狂!)


谢谢,但那正是我正在使用的。我正在寻找一个数组指针,所以我甚至不需要定义一个结构体。 - LS_ᴅᴇᴠ
关于优化收益:我将对b1[x*3+ch]fastpixel[x].R进行基准测试,以检查... - LS_ᴅᴇᴠ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接