【问题标题】:How can I read data faster?如何更快地读取数据?
【发布时间】:2011-06-01 10:58:56
【问题描述】:

嗯...找到一种读取/写入数据的方法以足够快的速度使用 F# 在这个问题 (https://www.spoj.pl/problems/INTEST/) 中被接受,这有点挑战。

我的代码 (http://paste.ubuntu.com/548748/) 获得 TLE...

任何想法如何加快数据读取?

【问题讨论】:

  • +1:我自己在 F# 中解决了一些 SPOJ 问题,也遇到了与 IO 相关的砖墙。
  • @cfern 我正在使用 C++、C# 和 F# 解决问题......但我希望 opp 使用 F# 解决所有问题......因为我认为并且我觉得这个 lang 是太棒了... :( 但是这些 TLE 让我发疯了...

标签: f# writing f#-data


【解决方案1】:

我实际上不知道,但我想一次阅读一个 since 字符是不好的,你应该阅读例如一次 4k 到一个缓冲区,然后处理该缓冲区。

【讨论】:

    【解决方案2】:
    let buf =
        let raw = System.Console.OpenStandardInput()
        let bytebuf = new System.IO.BufferedStream(raw)
        new System.IO.StreamReader(bytebuf)
    
    buf.Read()     // retrieves a single character as an int from the buffer
    buf.ReadLine() // retrieves a whole line from the buffer
    

    【讨论】:

      【解决方案3】:

      我的这个版本超过了时间限制(但仍然非常慢~14秒):

      open System
      open System.IO
      
      // need to change standard buffer, not to add an additional one
      let stream = new StreamReader(Console.OpenStandardInput(4096))
      
      let stdin = Seq.unfold (fun s -> if s = null then None else Some (s,stream.ReadLine())) <| stream.ReadLine()
      
      let inline s2i (s : string) = Array.fold (fun a d -> a*10u + (uint32 d - uint32 '0') ) 0u <| s.ToCharArray()
      
      let calc = 
          let fl = Seq.head stdin
          let [|_;ks|] = fl.Split(' ')
          let k = uint32 ks
          Seq.fold (fun a s -> if (s2i s) % k = 0u then a+1 else a) 0 <| Seq.skip 1 stdin
      
      printf "%A" calc
      

      虽然这个版本的瓶颈实际上是 string -&gt; uint32 转换(从字符串转换的标准 uint32 甚至更慢),但在我的示例输入(~100M 文件)上读取本身大约需要 2 秒(相对于总时间为 6 秒) ) - 仍然不是一个很好的结果。一旦s2i 被重写为命令式风格,spoj 上的总运行时间可以减少到 10 秒:

      let inline s2i (s : string) =
          let mutable a = 0u
          for i in 0..s.Length-1 do a <- a*10u + uint32 (s.Chars(i)) - uint32 '0'
          a
      

      【讨论】:

      • +1 因为它也对我有用。瓶颈确实是整数转换。在我的 PC 上,手动可变 s2i 的执行速度比标准的 int 函数快大约 6.3 倍。我还使用了一个 for 循环来读取数据,因为行数是事先知道的。我的解决方案在 6.35 秒时被接受。干得好!
      • for i in 0..s.Length-1 do 替换为for i=0 to s.Length-1 do
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 2018-10-21
      • 2021-04-28
      • 2011-06-07
      • 1970-01-01
      • 2017-03-26
      相关资源
      最近更新 更多