Haskell или F # высокопроизводительный двоичный ввод / вывод - PullRequest
11 голосов
/ 31 декабря 2010

Насколько хороша производительность двоичных библиотек ввода / вывода на этих двух языках> Я размышляю о переписывании некрасивого (но очень быстрого) кода C ++, который обрабатывает двоичные файлы размером около 5-10 ГБ с использованием стандартных функций fread и fwrite , Какой фактор замедления следует ожидать для оптимизированной реализации в F # и Haskell?

EDIT: здесь C-реализация подсчета нулевых байтов (буфер, выделенный на куче).

#include <stdio.h>
#include <stdlib.h>

#define SIZE 32*1024
int main(int argc, char* argv[])
{
    FILE *fp;
    char *buf;
    long i = 0, s = 0, l = 0;
    fp = fopen(argv[1], "rb");
    if (!fp) {
        printf("Openning %s failed\n", argv[1]);
        return -1;
    }
    buf = (char *) malloc(SIZE);
    while (!feof(fp)) {
        l = fread(buf, 1, SIZE, fp);
        for (i = 0; i &lt l; ++i) {
            if (buf[i] == 0) {
                ++s;
            }
        }
    }
    printf("%d\n", s);
    fclose(fp);
    free(buf);
    return 0;
}

Результаты:


$ gcc -O3 -o ioc io.c
$ ghc --make -O3 -o iohs io.hs
Linking iohs ...
$ time ./ioc 2.bin
462741044

real    0m16.171s
user    0m11.755s
sys     0m4.413s
$ time ./iohs 2.bin
4757708340

real    0m16.879s
user    0m14.093s
sys     0m2.783s
$ ls -lh 2.bin
-rw-r--r-- 1  14G Jan  4 10:05 2.bin

Ответы [ 3 ]

9 голосов
/ 31 декабря 2010

Haskell с использованием lazy IO на основе ByteString с «двоичным» синтаксическим анализатором должен иметь примерно ту же производительность, что и код C, выполняющий ту же работу, с теми же типами данных.

пакеты ключей, о которых следует знать:

8 голосов
/ 04 января 2011

Учитывая, что этот пост влечет за собой:

  • Haskell
  • оптимизация кода
  • показатели производительности

... можно с уверенностью сказать, что я нахожусь над моей головой. Тем не менее, я всегда чему-то учусь, когда захожу над головой, так что вот так.

Я начал изучать модули Data.ByteString.Lazy.* Haskell через Hoogle и нашел функцию length для измерения длины ленивой ByteString. Это реализовано таким образом:

length :: ByteString -> Int64
length cs = foldlChunks (\n c -> n + fromIntegral (S.length c)) 0 cs

Хм. Джон действительно сказал, что "... сворачивание более 1021 * кусков файла в F # является основной частью того, почему это быстро ..." (мой акцент). И эта length функция, по-видимому, также реализована с использованием короткого сгиба. Таким образом, похоже, что эта функция гораздо больше похожа на код «Яблоко», чем код Джона F #.

Имеет ли это значение на практике? Я сравнил пример Джона со следующим:

import System
import Data.List
import Data.ByteString.Lazy as B

main =
    getArgs
    >>= B.readFile . Data.List.head
    >>= print . B.length

Пример Jon's Haskell на моей машине для файла объемом 1,2 ГБ: 10,5 с

Версия «коренастый»: 1.1s

«Коренастая» версия кода на Haskell почти в десять раз быстрее. Что говорит о том, что он, вероятно, в несколько раз быстрее, чем оптимизированный код F # Джона.

EDIT

Хотя я не обязательно полностью согласен с критикой Джоном моего примера, я хотел бы сделать его настолько безупречным, насколько это возможно. Таким образом, я профилировал следующий код:

import System
import Data.List
import Data.ByteString.Lazy as B

main =
    getArgs
    >>= B.readFile . Data.List.head
    >>= print . B.count 0

Этот код загружает содержимое целевого файла в ByteString, а затем «подсчитывает» каждый случай появления байта с 0 значением. Если я что-то не упустил, эта программа должна загружать и оценивать каждый байт целевого файла.

Вышеуказанная программа работает примерно в 4 раза быстрее, чем последняя самая быстрая программа на Haskell, представленная Джоном, скопированная здесь для справки (в случае ее обновления):

import System
import Data.Int
import Data.List
import Data.ByteString.Lazy as B

main =
    getArgs
    >>= B.readFile . Data.List.head
    >>= print . B.foldl (\n c -> n + 1) (0 :: Data.Int.Int64)
2 голосов
/ 03 января 2011

Я писал об этом здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...