gpt4 book ai didi

c# - 如何固定通用 Span 实例以使用 Parallel.For 对其进行处理?

转载 作者:太空狗 更新时间:2023-10-29 19:43:35 25 4
gpt4 key购买 nike

我正在使用新的 Span<T> 重写我的一些扩展方法类型,我无法找到一种方法来正确固定通用实例,以便能够使用并行代码来处理它。

例如,考虑这个扩展方法:

public static unsafe void Fill<T>(this Span<T> span, [NotNull] Func<T> provider) where T : struct
{
int
cores = Environment.ProcessorCount,
batch = span.Length / cores,
mod = span.Length % cores,
sizeT = Unsafe.SizeOf<T>();
//fixed (void* p0 = &span.DangerousGetPinnableReference()) // This doesn't work, can't pin a T object
void* p0 = Unsafe.AsPointer(ref span.DangerousGetPinnableReference());
{
byte* p = (byte*)p0; // Local copy for the closure
Parallel.For(0, cores, i =>
{
byte* start = p + i * batch * sizeT;
for (int j = 0; j < batch; j++)
Unsafe.Write(start + sizeT * j, provider());
});

// Remaining values
if (mod == 0) return;
for (int i = span.Length - mod; i < span.Length; i++)
span[i] = provider();
}
}

这里我只想填一个输入Span<T>使用一些值提供程序,并且由于这些向量可能非常大,我想并行填充它们。

This is just an example, so even if using parallel code here isn't 100% necessary, the question still stands, as I'd need to use parallel code again sooner or later anyways.

现在,这段代码确实有效,但是因为我从来没有真正固定输入跨度并且考虑到它很可能指向某个托管的 T[] 的事实。 vector,它可以一直被 GC 移动,我想我可能只是幸运地看到它在我的测试中运行良好。

所以,我的问题是:

Is there any way to pin a generic Span<T> instance and get a simple void* pointer to it, so that I can pass it around in closures to work on the Span<T> instance in parallel code?

谢谢!

最佳答案

我想我可能已经使用 Unsafe 中的一种新方法找到了解决方法类,我已经对其进行了测试,到目前为止它似乎有效。在这里:

public static unsafe void Fill<T>(this Span<T> span, [NotNull] Func<T> provider) where T : struct
{
int
cores = Environment.ProcessorCount,
batch = span.Length / cores,
mod = span.Length % cores,
size = Unsafe.SizeOf<T>();
ref T r0 = ref span.DangerousGetPinnableReference();
fixed (byte* p0 = &Unsafe.As<T, byte>(ref r0))
{
byte* p = p0;
Parallel.For(0, cores, i =>
{
byte* pi = p + i * batch * size;
for (int j = 0; j < batch; j++, pi += size)
Unsafe.Write(pi, provider());
}).AssertCompleted();

// Remaining values
if (mod < 1) return;
for (int i = span.Length - mod; i < span.Length; i++)
Unsafe.Write(p + i * size, provider());
}
}

基本上,因为我无法固定 ref T值(value),我试图得到一个 ref byte变量使用 Unsafe.As<T, byte>(ref T value)并固定那个。由于它指向相同的地址,我认为(希望)它固定得很好,它应该在 IL 中做同样的事情。

关于c# - 如何固定通用 Span<T> 实例以使用 Parallel.For 对其进行处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48083037/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com