小编Asi*_*sik的帖子

Seq.map比常规for循环更快?

我正在学习F#,关于这种语言我最关心的一件事就是表现.我写了一个小基准,我将惯用的F#与用同一种语言编写的命令式代码进行比较 - 令我惊讶的是,功能版本的出现速度明显更快.

基准包括:

  1. 使用File.ReadAllLines读取文本文件
  2. 颠倒每行内的字符顺序
  3. 使用File.WriteAllLines将结果写回同一文件.

这是代码:

open System
open System.IO
open System.Diagnostics

let reverseString(str:string) =
    new string(Array.rev(str.ToCharArray()))

let CSharpStyle() = 
    let lines = File.ReadAllLines("text.txt")
    for i in 0 .. lines.Length - 1 do
        lines.[i] <- reverseString(lines.[i])

    File.WriteAllLines("text.txt", lines)

let FSharpStyle() = 
    File.ReadAllLines("text.txt")
    |> Seq.map reverseString
    |> (fun lines -> File.WriteAllLines("text.txt", lines))

let benchmark func message = 
    // initial call for warm-up
    func()

    let sw = Stopwatch.StartNew()
    for i in 0 .. 19 do
        func()

    printfn message sw.ElapsedMilliseconds


[<EntryPoint>] …
Run Code Online (Sandbox Code Playgroud)

performance f#

8
推荐指数
1
解决办法
415
查看次数

foreach vs for:请解释汇编代码差异

我最近一直在测试for循环与C#中的foreach循环的性能,我注意到,为了将一个int数组合成一个long,foreach循环可能实际上更快.这是完整的测试程序,我使用了Visual Studio 2012,x86,发布模式,优化.

这是两个循环的汇编代码.foreach:

            long sum = 0;
00000000  push        ebp 
00000001  mov         ebp,esp 
00000003  push        edi 
00000004  push        esi 
00000005  push        ebx 
00000006  xor         ebx,ebx 
00000008  xor         edi,edi 
            foreach (var i in collection) {
0000000a  xor         esi,esi 
0000000c  cmp         dword ptr [ecx+4],0 
00000010  jle         00000025 
00000012  mov         eax,dword ptr [ecx+esi*4+8] 
                sum += i;
00000016  mov         edx,eax 
00000018  sar         edx,1Fh 
0000001b  add         ebx,eax 
0000001d  adc         edi,edx 
0000001f  inc         esi 
            foreach (var i in collection) {
00000020  cmp         dword …
Run Code Online (Sandbox Code Playgroud)

c# performance x86 assembly

8
推荐指数
2
解决办法
1179
查看次数

F#编码风格 - 静态与实例方法

我注意到静态方法在F#中比C#更受欢迎.在C#中,您总是通过调用实例方法向集合添加元素:

mySet.Add(elem);
Run Code Online (Sandbox Code Playgroud)

但是在F#中通常有一个等效的静态方法:

mySet.Add(elem)
// OR
Set.Add elem mySet
Run Code Online (Sandbox Code Playgroud)

而且我经常在样本中看到后一种形式.在我看来,两者在语义和功能上完全相同,但是来自C#背景,使用实例方法感觉更自然.哪个是F#更好的风格?为什么?

c# f# coding-style

7
推荐指数
2
解决办法
615
查看次数

如何重构所需的else子句?

我有一个看起来有点像这样的C#方法:

bool Eval() {
  // do some work
  if (conditionA) {
     // do some work
     if (conditionB) {
       // do some work
       if (conditionC) {
         // do some work
         return true;
       }
     }
  }
  return false;
}
Run Code Online (Sandbox Code Playgroud)

在F#中,由于强制性的其他分支,这最终看起来有点丑陋:

let eval() =
  // do some work
  if conditionA then
    // do some work
    if conditionB then
      // do some work
      if conditionC then
        // do some work
        true
      else
        false
    else
      false
  else
    false
Run Code Online (Sandbox Code Playgroud)

用F#写这个更干净的方法是什么?

c# f#

7
推荐指数
4
解决办法
581
查看次数

IntelliSense错误:引用无法绑定到initonly字段?

我有一个像这样的C++/CLI类:

// MyClass.h
#pragma once

namespace MyNamespace {
    using namespace System;

    public ref class MyClass {
    private:
        MyClass();
        IntPtr m_ptr;
    };
}

// MyClass.cpp
#include "MyClass.h"
using namespace System;

namespace MyNamespace {
    MyClass::MyClass() {
        m_ptr = IntPtr::Zero;
    }
}
Run Code Online (Sandbox Code Playgroud)

项目编译时没有错误或警告,但是该行m_ptr = IntPtr::Zero总是带有下划线红色,并带有IntelliSense错误:"引用不能绑定到initonly字段".是什么赋予了?我怎么能摆脱这个?

这是在Visual Studio 2012 Premium Edition中,但Platform Toolset是Visual Studio 2008(v90).

.net c++-cli

7
推荐指数
1
解决办法
429
查看次数

为什么结构值必须是可变的来设置索引属性?

考虑以下程序:

[<Struct>]
type Grid2D<'T> = 
    val RowLength : int
    val Data : 'T[]
    new(rowLength, data) = { RowLength = rowLength; Data = data }

    member this.Item
        with get(rowIndex, columnIndex) = 
            this.Data.[rowIndex * this.RowLength + columnIndex]
        and set(rowIndex, columnIndex) value = 
            this.Data.[rowIndex * this.RowLength + columnIndex] <- value

let g = Grid2D(3, Array.zeroCreate(3 * 3))
g.[1, 1] <- 4
Run Code Online (Sandbox Code Playgroud)

最后一行无法编译:

错误FS0256:值必须是可变的才能改变内容或获取值类型的地址,例如'let mutable x = ...'

但是,如果[<Struct>]删除该属性,并且Grid2D因此是引用类型,则程序将编译.

有趣的是,手动内联属性setter也很好:

g.Data.[1 * g.RowLength + 1] <- 4
Run Code Online (Sandbox Code Playgroud)

那么为什么称它为编译错误?

注意:我知道存在此编译器错误,因此无法通过设置其中一个字段来改变结构的非可变值.但我显然没有在这里改变结构.

f#

7
推荐指数
1
解决办法
202
查看次数

TryParse的重载解析

我们有一个函数,可以将类似的事情Int32.TryParse从使用byref 转换为使用Option作为返回值。

let inline ToOptionFunc refFunction x =
    match refFunction x with
    | true, value  -> Some value
    | false, _     -> None
Run Code Online (Sandbox Code Playgroud)

像这样的东西由于对TryParse的新重载而停止在.NET Core中进行编译:

let Int32TryParse (x:string) =
     ToOptionFunc Int32.TryParse x // A unique overload for method 'TryParse' could not be determined (...)
Run Code Online (Sandbox Code Playgroud)

我尝试了很多事情,并通过这样写来偶然地使它起作用:

let Int32TryParse (x:string) =
     x |> ToOptionFunc Int32.TryParse
Run Code Online (Sandbox Code Playgroud)

我只是不明白为什么编译,而前者却不编译。

f#

7
推荐指数
1
解决办法
70
查看次数

未解决的外部尝试使用ffmpeg

我正在尝试使用ffmpeg中的一些函数,并且遇到了弹性链接器错误.这是我做的:

  • http://ffmpeg.zeranoe.com/builds/下载最新的32位"Dev"版本(即ffmpeg-20130418-git-ee94362-win32-dev)
  • 在Visual Studio 2012 Premium中创建了"常规 - 空"C++项目
  • 将[ffmpeg]/lib文件夹添加到链接器 - >输入 - >"其他库目录"
  • 添加了"swscale.lib; avutil.lib; avformat.lib; avdevice.lib; avcodec.lib;" 链接器 - >输入 - >"附加依赖项"
  • 在C++ - > General - > Additional Include Directories下添加了以下内容:
    • [FFMPEG] /包括
    • [FFMPEG] /包含/ libswscale
    • [FFMPEG] /包含/了libavformat

这是我的main.cpp:

#include "avformat.h"

int main()
{
    av_register_all();
} 
Run Code Online (Sandbox Code Playgroud)

这失败了:

错误LNK2019:函数_main中引用的未解析的外部符号"void __cdecl av_register_all(void)"(?av_register_all @@ YAXXZ)

我该如何解决这个错误?

c++ linker ffmpeg

6
推荐指数
1
解决办法
5737
查看次数

如何将两组4条短路装入XMM寄存器?

我刚刚开始使用Visual C++ 2012的SSE内在函数,我需要一些指针(没有双关语).

我有两个signed short每个包含4个的数组(每个数组因此是64位,总共128个).我想将一个加载到XMM寄存器的高位,另一个加载到低位.我可以使用SSE内在函数有效地实现这一目标吗?如果是这样,怎么样?

c++ x86 sse simd intrinsics

6
推荐指数
1
解决办法
849
查看次数

如何检测 WPF 控件何时被重绘?

我正在使用 D3DImage 显示一系列帧,这些帧依次渲染到同一个 Direct3D Surface 上。我目前的逻辑是:

  • 显示最后渲染的帧(即D3DImage.Lock()/AddDirtyRect()/Unlock())
  • 开始渲染下一帧
  • 等待下一帧准备好并显示它
  • 显示最后渲染的帧
  • ...

这种方法的问题在于,当我们在 D3DImage 上调用 Unlock() 后,图像实际上并未被复制,它只是计划在下一个 WPF 渲染时复制。因此,我们有可能在 WPF 有机会显示新帧之前在 Direct3D 表面上渲染它。最终结果是我们在显示屏上看到丢失的帧。

现在,我正在尝试使用单独的 Direct3D 纹理进行渲染,并在显示之前执行到“显示纹理”的复制,这提供了更好的结果,但会产生大量开销。最好能够知道 D3DImage 何时完成刷新并立即开始渲染下一帧。这可能吗,如果可以的话怎么办?或者你有更好的主意吗?

谢谢。

c# directx wpf

6
推荐指数
1
解决办法
1797
查看次数

标签 统计

f# ×5

c# ×4

c++ ×2

performance ×2

x86 ×2

.net ×1

assembly ×1

c++-cli ×1

coding-style ×1

directx ×1

ffmpeg ×1

intrinsics ×1

linker ×1

simd ×1

sse ×1

wpf ×1