【问题标题】:Common Lisp: The fastest way to read the streamCommon Lisp:读取流的最快方法
【发布时间】:2011-05-27 12:10:25
【问题描述】:

伙计们,在 Common Lisp (SBCL) 中读取流的最快方法是什么?

对我来说,这就是 read-line。但突然间我遇到了这个函数的性能问题——我应该在 1.5 秒内读取 10kk 个字符(1000 行,每个字符 10000 个字符),但 read-line 未能实现。 Common Lisp 可以吗?是否提供了 C 风格的 scanf() 函数以便快速阅读?

谢谢!

更新。代码:

(defun split (string)
  (let ((space-position (position #\Space string)))
    (list 
     (subseq string 0 space-position) 
     (subseq string (+ space-position 1)))))

(defun solve (line)
  (let ((nums (split line))
    (first)
    (second))
    (setq first (parse-integer (car nums)))
    (setq second (parse-integer (cadr nums)))

    (* first second)))

(defun spoj()
  (let ((N (read))
        (line))
    (dotimes (i N)
      (setq line (read-line))
      (format t "~d~%" (solve line))))))

(spoj)

【问题讨论】:

  • 您的瓶颈很可能是您在 read-line 他们之后对字符串所做的事情。您可以发布您正在使用的代码吗?
  • 我正在使用 SBCL。但看来你是对的。读取流后,应用程序逻辑代码中发生缓慢的事情。实际上,我通过长算术使用 parse-integer 和乘法。所以应用程序读取 1000 对整数(每个人 10^4 位)并打印出每对整数相乘的结果。

标签: common-lisp sbcl


【解决方案1】:

面向文本的 I/O 的性能在不同的实现之间会有很大差异,有助于提高一种实现性能的策略可能不适用于另一种实现。您使用的是什么实现方式?

是否保证行的长度相同?

不管怎样,我尝试了你的练习(1000 行,每行 10000 个字符),在 SBCL 中阅读大约需要 0.25 秒。

【讨论】:

  • 我正在使用 SBCL。现在我认为这不是 I/O 问题。
【解决方案2】:

如果不进行分析,就无法准确判断瓶颈在哪里,但我的猜测是 splitsolve 正在减慢您的速度。具体来说,当您在字符串上调用subseq 来拆分它时,您最终会分配两个新字符串。由于parse-integer 可以将开始和结束索引放入字符串中,因此无需进行拆分:

(let* ((space-position (position #\Space string))
       (first (parse-integer string :end space-position))
       (second (parse-integer string :start (1+ space-position)))
  (* first second))

【讨论】:

  • PARSE-INTEGER 返回它消耗多少字符串的第二个值,因此您也可以使用 (m-v-b (first end) (parse-integer string :junk-allowed t) (* first (解析整数字符串 :start (1+ end) :junk-allowed t))) 或类似的。
猜你喜欢
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
相关资源
最近更新 更多