如何使用Parallel.For固定一个通用的Span 实例来处理它?
我正在使用新的Span
类型重写我的一些扩展方法,并且我无法找到正确固定通用实例的方法,以便能够使用并行代码来处理它。
例如,考虑这种扩展方法:
public static unsafe void Fill(this Span span, [NotNull] Func provider) where T : struct { int cores = Environment.ProcessorCount, batch = span.Length / cores, mod = span.Length % cores, sizeT = Unsafe.SizeOf(); //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
,因为这些向量可能非常大,所以我想并行填充它们。
这只是一个例子,所以即使在这里使用并行代码不是100%必要的,问题仍然存在,因为我需要迟早再次使用并行代码。
现在,这段代码确实有效 ,但是因为我从来没有实际固定输入范围并且事实上它很可能指向一些托管的T[]
向量,它可以被GC一直移动,我我想我可能很幸运,看到它在我的测试中运行良好。
所以,我的问题是:
有没有办法固定一个通用的
Span
实例并获得一个简单的void*
指针,以便我可以在闭包中传递它来处理并行代码中的Span
实例?
谢谢!
我想我可能已经找到了使用Unsafe
类中的一个新方法的解决方法,我已经对它进行了测试,到目前为止似乎有效。 这里是:
public static unsafe void Fill(this Span span, [NotNull] Func provider) where T : struct { int cores = Environment.ProcessorCount, batch = span.Length / cores, mod = span.Length % cores, size = Unsafe.SizeOf (); ref T r0 = ref span.DangerousGetPinnableReference(); fixed (byte* p0 = &Unsafe.As(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
值,所以我尝试使用Unsafe.As
来获取ref byte
变量Unsafe.As
并将其固定。 因为它指向相同的地址,我认为(希望)它固定得很好,它应该在IL中做同样的事情。
- 创建为.Net Auth Cookie交换自定义令牌的Owin Auth Provider
- 使用Moq对LINQ to SQL CRUD操作进行unit testing
- 你是否必须为异步方法调用调用EndInvoke(或定义一个回调),即使你返回时没有任何事情要做
- CS0103 C#当前上下文中不存在名称“Json”
- 如何在/ .Net中拦截来自/到第三方库的非虚拟方法的调用?
- 如何将文件合并到单个可执行文件或减少分布式文件的数量
- FindWindow和SetForegroundWindow的替代品?
- Visual Studio注册表捕获实用程序已停止工作,在Windows7中编译C#项目时出错
- 将围绕DataReader放置一个“using”语句关闭吗?