mirror of https://github.com/SixLabors/ImageSharp
4 changed files with 39 additions and 207 deletions
@ -1,62 +0,0 @@ |
|||
using System; |
|||
using System.Buffers; |
|||
using System.Threading.Tasks; |
|||
|
|||
using SixLabors.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Utility methods for Parallel.For() execution. Use this instead of raw <see cref="Parallel"/> calls!
|
|||
/// </summary>
|
|||
internal static class ParallelFor |
|||
{ |
|||
/// <summary>
|
|||
/// Helper method to execute Parallel.For using the settings in <paramref name="configuration"/>
|
|||
/// </summary>
|
|||
public static void WithConfiguration(int fromInclusive, int toExclusive, Configuration configuration, Action<int> body) |
|||
{ |
|||
Parallel.For(fromInclusive, toExclusive, configuration.GetParallelOptions(), body); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Helper method to execute Parallel.For with temporary worker buffer shared between executing tasks.
|
|||
/// The buffer is not guaranteed to be clean!
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The value type of the buffer</typeparam>
|
|||
/// <param name="fromInclusive">The start index, inclusive.</param>
|
|||
/// <param name="toExclusive">The end index, exclusive.</param>
|
|||
/// <param name="configuration">The <see cref="Configuration"/> used for getting the <see cref="MemoryAllocator"/> and <see cref="ParallelOptions"/></param>
|
|||
/// <param name="bufferLength">The length of the requested parallel buffer</param>
|
|||
/// <param name="body">The delegate that is invoked once per iteration.</param>
|
|||
public static void WithTemporaryBuffer<T>( |
|||
int fromInclusive, |
|||
int toExclusive, |
|||
Configuration configuration, |
|||
int bufferLength, |
|||
Action<int, IMemoryOwner<T>> body) |
|||
where T : struct |
|||
{ |
|||
MemoryAllocator memoryAllocator = configuration.MemoryAllocator; |
|||
ParallelOptions parallelOptions = configuration.GetParallelOptions(); |
|||
|
|||
IMemoryOwner<T> InitBuffer() |
|||
{ |
|||
return memoryAllocator.Allocate<T>(bufferLength); |
|||
} |
|||
|
|||
void CleanUpBuffer(IMemoryOwner<T> buffer) |
|||
{ |
|||
buffer.Dispose(); |
|||
} |
|||
|
|||
IMemoryOwner<T> BodyFunc(int i, ParallelLoopState state, IMemoryOwner<T> buffer) |
|||
{ |
|||
body(i, buffer); |
|||
return buffer; |
|||
} |
|||
|
|||
Parallel.For(fromInclusive, toExclusive, parallelOptions, InitBuffer, BodyFunc, CleanUpBuffer); |
|||
} |
|||
} |
|||
} |
|||
@ -1,115 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
using BenchmarkDotNet.Attributes; |
|||
|
|||
using SixLabors.ImageSharp.Advanced; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Benchmarks.Codecs |
|||
{ |
|||
public class CopyPixels : BenchmarkBase |
|||
{ |
|||
[Benchmark(Baseline = true, Description = "PixelAccessor Copy by indexer")] |
|||
public Rgba32 CopyByPixelAccesor() |
|||
{ |
|||
using (var source = new Image<Rgba32>(1024, 768)) |
|||
using (var target = new Image<Rgba32>(1024, 768)) |
|||
{ |
|||
Buffer2D<Rgba32> sourcePixels = source.GetRootFramePixelBuffer(); |
|||
Buffer2D<Rgba32> targetPixels = target.GetRootFramePixelBuffer(); |
|||
ParallelFor.WithConfiguration( |
|||
0, |
|||
source.Height, |
|||
Configuration.Default, |
|||
y => |
|||
{ |
|||
for (int x = 0; x < source.Width; x++) |
|||
{ |
|||
targetPixels[x, y] = sourcePixels[x, y]; |
|||
} |
|||
}); |
|||
|
|||
return targetPixels[0, 0]; |
|||
} |
|||
} |
|||
|
|||
[Benchmark(Description = "PixelAccessor Copy by Span")] |
|||
public Rgba32 CopyByPixelAccesorSpan() |
|||
{ |
|||
using (var source = new Image<Rgba32>(1024, 768)) |
|||
using (var target = new Image<Rgba32>(1024, 768)) |
|||
{ |
|||
Buffer2D<Rgba32> sourcePixels = source.GetRootFramePixelBuffer(); |
|||
Buffer2D<Rgba32> targetPixels = target.GetRootFramePixelBuffer(); |
|||
ParallelFor.WithConfiguration( |
|||
0, |
|||
source.Height, |
|||
Configuration.Default, |
|||
y => |
|||
{ |
|||
Span<Rgba32> sourceRow = sourcePixels.GetRowSpan(y); |
|||
Span<Rgba32> targetRow = targetPixels.GetRowSpan(y); |
|||
|
|||
for (int x = 0; x < source.Width; x++) |
|||
{ |
|||
targetRow[x] = sourceRow[x]; |
|||
} |
|||
}); |
|||
|
|||
return targetPixels[0, 0]; |
|||
} |
|||
} |
|||
|
|||
[Benchmark(Description = "Copy by indexer")] |
|||
public Rgba32 Copy() |
|||
{ |
|||
using (var source = new Image<Rgba32>(1024, 768)) |
|||
using (var target = new Image<Rgba32>(1024, 768)) |
|||
{ |
|||
ParallelFor.WithConfiguration( |
|||
0, |
|||
source.Height, |
|||
Configuration.Default, |
|||
y => |
|||
{ |
|||
for (int x = 0; x < source.Width; x++) |
|||
{ |
|||
target[x, y] = source[x, y]; |
|||
} |
|||
}); |
|||
|
|||
return target[0, 0]; |
|||
} |
|||
} |
|||
|
|||
[Benchmark(Description = "Copy by Span")] |
|||
public Rgba32 CopySpan() |
|||
{ |
|||
using (var source = new Image<Rgba32>(1024, 768)) |
|||
using (var target = new Image<Rgba32>(1024, 768)) |
|||
{ |
|||
ParallelFor.WithConfiguration( |
|||
0, |
|||
source.Height, |
|||
Configuration.Default, |
|||
y => |
|||
{ |
|||
Span<Rgba32> sourceRow = source.Frames.RootFrame.GetPixelRowSpan(y); |
|||
Span<Rgba32> targetRow = target.Frames.RootFrame.GetPixelRowSpan(y); |
|||
|
|||
for (int x = 0; x < source.Width; x++) |
|||
{ |
|||
targetRow[x] = sourceRow[x]; |
|||
} |
|||
}); |
|||
|
|||
return target[0, 0]; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue