forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   C++ (http://forum.boolean.name/forumdisplay.php?f=22)
-   -   высокопроизводительный код или кунг-фу в исполнении lz4 (http://forum.boolean.name/showthread.php?t=17262)

jimon 05.09.2012 03:46

высокопроизводительный код или кунг-фу в исполнении lz4
 
давненько я не видал стоящего кода на C, но тут мне в глаза попался lz4 : http://code.google.com/p/lz4/

это библиотека компрессии и распаковки данных, судя по тестам она далеко обошла snappy (http://code.google.com/p/snappy/ один из быстрейших архиваторов, разработан и используется гуглом), а качество сжатия на уровне zlib

библиотека написана чтобы выжать всё без ориентировки на конкретный cpu (быстрее будут аппаратно заточенный код), в коде обширно используются встроенные функции компилятора

к примеру :
Код:

if unlikely(cpy>oend-COPYLENGTH)
что же это за unlikely ? а вот что :
Код:

#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
#  define expect(expr,value)    (__builtin_expect ((expr),(value)) )
#else
#  define expect(expr,value)    (expr)
#endif

#define likely(expr)    expect((expr) != 0, 1)
#define unlikely(expr)  expect((expr) != 0, 0)

где функция :
Цитата:

— Built-in Function: long __builtin_expect (long exp, long c)

You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect.
те исходя из анализа данных мы делаем вывод о вероятности события и заставляем компилятор учитывать это для предсказателя ветвлений, кунг-фу ! :crazy:

или другой пример :
Код:

// Unaligned memory access is automatically enabled for "common" CPU, such as x86.
// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected
// If you know your target CPU supports unaligned memory access, you may want to force this option manually to improve performance
#if defined(__ARM_FEATURE_UNALIGNED)
#  define LZ4_FORCE_UNALIGNED_ACCESS 1
#endif

как мы знаем (или узнаем) RISC архитектуры выдают максимум только если тип выравнен на размер, те MIPS и некоторые ARM'ы требуют чтобы short был выравнен на 2 байта, int на 4 байта, (для справки, ARM до сих пор требует чтобы float был выравнен на 4 байта, если нет то clang будет генерировать просто не валидный код, потому при играх с выравниванием ваш код может просто не разработать)

а теперь посмотрим как это здесь реализовано :
Код:

#if defined(_MSC_VER)    // Visual Studio does not support 'stdint' natively
#  define BYTE        unsigned __int8
#  define U16                unsigned __int16
#  define U32                unsigned __int32
#  define S32                __int32
#  define U64                unsigned __int64
#else
#  include <stdint.h>
#  define BYTE        uint8_t
#  define U16                uint16_t
#  define U32                uint32_t
#  define S32                int32_t
#  define U64                uint64_t
#endif

#ifndef LZ4_FORCE_UNALIGNED_ACCESS
#  pragma pack(push, 1)
#endif

typedef struct _U16_S { U16 v; } U16_S;
typedef struct _U32_S { U32 v; } U32_S;
typedef struct _U64_S { U64 v; } U64_S;

#ifndef LZ4_FORCE_UNALIGNED_ACCESS
#  pragma pack(pop)
#endif

#define A64(x) (((U64_S *)(x))->v)
#define A32(x) (((U32_S *)(x))->v)
#define A16(x) (((U16_S *)(x))->v)

довольно красиво, да ? при включенном макросе компилятор просто выравняет поля в структуре как нужно, а при выключенном мы форсируем ему выравнивание на 1 байт

думаю заинтересовал обывателя по-изучать исходник для саморазвития :crazy:

Platon 05.09.2012 13:20

Ответ: высокопроизводительный код или кунг-фу в исполнении lz4
 
+1, еще стоит глянуть это yappy


Часовой пояс GMT +4, время: 11:39.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot