(顺便说一句.这是指32位操作系统)
一些更新:
这绝对是一个对齐问题
有时对齐(无论出于什么原因?)是如此糟糕,以至于对双倍的访问速度比其最快访问速度慢50倍.
在64位机器上运行代码减少了问题,但我认为它仍然在两个时间之间交替(我可以通过将双倍更改为32位机器上的浮点数来获得类似结果)
在mono下运行代码没有问题 - 微软,你有没有机会从那些Novell家伙那里复制一些东西?
有没有办法在c#中记忆对齐类的分配?
以下演示(我认为!)没有双打正确对齐的不良.它对存储在类中的double执行一些简单的数学计算,对每次运行进行计时,在变量上运行5次定时运行,然后再分配新的并重新执行.
基本上结果看起来像你有一个快速,中等或慢速的记忆位置(在我的古代处理器上,这些最终每次运行大约40,80或120ms)
我曾尝试使用StructLayoutAttribute,但没有任何乐趣 - 也许还有其他事情正在发生?
class Sample
{
class Variable { public double Value; }
static void Main()
{
const int COUNT = 10000000;
while (true)
{
var x = new Variable();
for (int inner = 0; inner < 5; ++inner)
{
// move allocation here to allocate more often so more probably to get 50x slowdown problem
var stopwatch = Stopwatch.StartNew();
var total = 0.0;
for (int i = 1; …Run Code Online (Sandbox Code Playgroud) FWIW我认为这里详述的问题归结为c#编译器更智能,并且使得基于状态机的高效模型能够处理异步代码,而F#编译器创建了大量通常效率较低的对象和函数调用.
无论如何,如果我有下面的c#函数:
public async static Task<IReadOnlyList<T>> CSharpAsyncRead<T>(
SqlCommand cmd,
Func<SqlDataReader, T> createDatum)
{
var result = new List<T>();
var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
var datum = createDatum(reader);
result.Add(datum);
}
return result.AsReadOnly();
}
Run Code Online (Sandbox Code Playgroud)
然后将其转换为F#,如下所示:
let fsharpAsyncRead1 (cmd:SqlCommand) createDatum = async {
let! reader =
Async.AwaitTask (cmd.ExecuteReaderAsync ())
let rec readRows (results:ResizeArray<_>) = async {
let! readAsyncResult = Async.AwaitTask (reader.ReadAsync ())
if readAsyncResult then
let datum = createDatum reader
results.Add datum
return! readRows results
else
return results.AsReadOnly() :> …Run Code Online (Sandbox Code Playgroud) 更新:之前提到的跨度问题已在 .net core 2.1 版本(目前处于预览版)中得到修复。这些实际上使跨度向量 * 比数组向量更快 * ...
注意:在“Intel Xeon E5-1660 v4”上进行测试,CPU-Z 告诉我有“MMX、SSE、SSE2、SSE3、SSSE3、SSE4.1、SSE4.2、EM64T、VT-x、AES、 AVX、AVX2、FMA3、RSX”所以应该没问题......
在回答基于Vector 的问题之后,我想我会尝试实现一些 BLAS 功能。我发现那些正在读取/求和(例如点积)的内容非常好,但是我写回数组的内容很糟糕 - 比非 SIMD 好,但几乎没有。
那么我做错了什么,还是需要在 JIT 中做更多的工作?
示例(假设 x.Length = y.Length,不为 null 等等等等):
public static void daxpy(double alpha, double[] x, double[] y)
{
for (var i = 0; i < x.Length; ++i)
y[i] = y[i] + x[i] * alpha;
}
Run Code Online (Sandbox Code Playgroud)
以向量形式变为:
public static void daxpy(double alpha, double[] x, double[] y)
{
var i = 0;
if (Vector.IsHardwareAccelerated)
{
var …Run Code Online (Sandbox Code Playgroud)