简体   繁体   中英

Jagged array, copy with offset

I am trying to copy one jagged array into another jagged array with given offset. I came up with the following:

private void CopyWithOffset(char[][] buffer, (int row, int col) offset)
{
    if (buffer == null) throw new ArgumentNullException(nameof(buffer));

    for (var row = 0; row < buffer.Length; row++)
    {
        try
        {
            for (var col = 0; col < buffer[row].Length; col++)
            {
                try
                {
                    _buffer[row + offset.row][col + offset.col] = buffer[row][col];
                }
                catch (IndexOutOfRangeException){}
            }
        } catch(IndexOutOfRangeException){}
    }
}

Unfortunately it is very slow. Is there any way to do it faster?

As noted in this comment , exception handling is very expensive, and if you use it as a normal control-flow mechanism in your code, it will make that code very slow.

You can easily avoid exceptions by just writing the code so that it doesn't use out-of-range index values in the first place:

private void CopyWithOffset(char[][] buffer, (int row, int col) offset)
{
    if (buffer == null) throw new ArgumentNullException(nameof(buffer));

    for (var row = 0; row < buffer.Length; row++)
    {
        for (var col = 0; col < buffer[row].Length ; col++)
        {
            int i = row + offset.row;

            if (i < _buffer.Length)
            {
                int j = col + offset.col;

                if (j < _buffer[i].Length)
                {
                    _buffer[i][j] = buffer[row][col];
                }
            }
        }
    }
}

As suggested by @Steve avoiding going out of index and iterating over necessary part of an array instead of iterating over the entire array pays of greatly.

Combine it with Parallel.For and Array.Copy (it should make use of SIMD extension more info here ) and one pretty much have lighting fast array copy function.

public static void CopyWithOffset(char[][] buffer, int x, int y)
{
    var rowStart = Math.Max(Math.Min(y, _buffer.Length), 0);
    var rowLenght = _buffer.Length + Math.Min(y, 0);

    Parallel.For(rowStart, rowLenght, row =>
    {
        var colStart = Math.Max(Math.Min(x, _buffer[row].Length), 0);
        var colLength = _buffer[row].Length + Math.Min(x, -1);

        Array.Copy(buffer[row - y], colStart - x, _buffer[row], colStart, colLength);
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM