Хобрук: Ваш путь к мастерству в программировании

Каков наиболее эффективный способ в Java упаковать биты в byte[] и прочитать их обратно?

В настоящее время я использую эти две функции для упаковки и чтения битов в массиве байтов. Хотите знать, есть ли у кого-нибудь лучшие идеи или более быстрые способы сделать это?

Отредактировал программу, еще немного оптимизировав ее и занеся в таблицу несколько расчетов. В настоящее время 100 мил Put and Get занимает около 12 секунд вместо 16 секунд.

Если кто-то использует текущий код, убедитесь, что значение, переданное в Put, является положительным числом, так как оно ожидает беззнаковые числа. Если есть интерес, могу выложить подписанную и неподписанную версии.

class BitData
{
    static void Put(byte Data[], final int BitOffset, int NumBits, final int Value)
    {
        final long valLong=(Value&((1L<<NumBits)-1L));
        int posByte=BitOffset>>3;
        int posBit=BitOffset&7;
        int valByte;
        int ModifyBits;

        long lValue;
        int LeftShift;
        ModifyBits=8-posBit;
        if(NumBits<ModifyBits) ModifyBits=NumBits;
        LeftShift=(8-posBit-ModifyBits);
        while(true)
        {
            valByte = Data[posByte];
            if(ModifyBits==8)
            {
                lValue=valLong<<(32-NumBits)>>(24);
                Data[posByte]=(byte)lValue;
            }
            else
            {   
                lValue=valLong<<(32-NumBits)>>(32-ModifyBits)<<LeftShift;
                Data[posByte]=(byte)((valByte & ~(((1<<ModifyBits)-1) << LeftShift)) | lValue);
            }
            NumBits-=ModifyBits;
            if(NumBits==0) break;
            posByte++;          
            ModifyBits=8;
            if(NumBits<ModifyBits) 
            {
                ModifyBits=NumBits;
                LeftShift=(8-ModifyBits);
            }
        }
    }

    static int GetInt(byte Data[], final int BitOffset, int NumBits)
    {       
        int posByte=BitOffset>>3;
        int posBit=BitOffset&7;


        long Value=0;
        int ModifyBits;
        int valByte;
        int LeftShift;
        ModifyBits=8-posBit;
        if(NumBits<ModifyBits) ModifyBits=NumBits;
        LeftShift=(8-posBit-ModifyBits);
        while(true)
        {
            valByte = Data[posByte] & 0xff;
            if(ModifyBits==8) Value+=valByte;
            else Value+=(valByte & ((1<<ModifyBits)-1) << LeftShift) >> LeftShift;              
            NumBits-=ModifyBits;
            if(NumBits==0) break;
            posByte++;
            ModifyBits=8;
            if(NumBits<ModifyBits) 
            {
                ModifyBits=NumBits;
                LeftShift=(8-ModifyBits);
            }
            Value<<=ModifyBits;

        }
        return (int)Value;
    }
}

  • Рассматривали ли вы возможность использования встроенного java.util.BitSet? 30.09.2011
  • Ага пробовал сначала. Это было намного медленнее, чем этот метод. Это сервер, который должен упаковывать и распаковывать, возможно, миллионы пакетов в секунду, поэтому ему нужен самый быстрый способ сделать это. Я сделал столько оптимизаций, сколько мог, с этими двумя функциями. Просто любопытно, есть ли в Java совершенно другой маршрут, о котором я не думал. 30.09.2011
  • да. Напишите его на C и используйте JNI для взаимодействия с Java. 30.09.2011
  • Программа также должна быть портативной. Я не знаком с JNI. Можете ли вы сказать мне, можно ли по-прежнему запускать программу на разных серверах ОС, если я пойду по этому пути? 30.09.2011
  • Я мало что знаю о JNI. Поскольку код JNI не будет выполнять ввод-вывод или взаимодействовать с ОС, я ожидаю, что различия будут очень и очень незначительными. Вам может сойти с рук один источник, но вам потребуется распространять двоичный файл для каждой комбинации ОС/оборудования. 30.09.2011
  • Да, это не сработало бы слишком хорошо для клиента. У меня нет никакого контроля над тем, какую ОС они будут использовать или могут использовать в будущем. 30.09.2011
  • @JimGarrison - есть ли у вас какой-либо сравнительный анализ, показывающий, что ускорение такого небольшого вычисления превысит накладные расходы на вызов метода JNI? (К ОП - я думаю, что это плохой совет.) 30.09.2011
  • @StephenC - Не совсем так. Если вы провели некоторый бенчмаркинг и думаете, что накладные расходы JNI превысят стоимость вычислений, я отзову свое предложение. 30.09.2011
  • @JimGarrison - я сам не проводил никаких тестов, но ... javamex.com/tutorials /jni/overhead.shtml и java .sun.com/docs/books/performance/1st_edition/html/ 02.10.2011

Ответы:


1

Совершенно другим путем было бы определить статическую таблицу всех возможных комбинаций и выполнять поиск вместо того, чтобы каждый раз вычислять результаты. Я думаю, что так они делают это в криптографии. array[i] x 3 должен быть намного быстрее, чем побитовые операции numBits. Однако он займет некоторую кучу.

30.09.2011
  • Постараюсь составить таблицу некоторых частей, чтобы увидеть, есть ли увеличение скорости. 30.09.2011
  • Две таблицы, которые я добавил, улучшили производительность примерно на 7-10 процентов. Не могу найти ничего другого в коде, который подходит для таблицы. 10-процентный выигрыш по-прежнему хорош. 30.09.2011
  • Новые материалы

    Деревья классификации и регрессии
    Это мой второй пост об алгоритмах машинного обучения. Мой первый пост посвящен искусственным нейронным сетям, вы можете найти его ниже. Нейронные сети — базовое..

    HMTL - Многозадачное обучение для решения задач НЛП
    Достижение результатов SOTA путем передачи знаний между задачами Область обработки естественного языка включает в себя десятки задач, среди которых машинный перевод, распознавание именованных..

    Решения DBA Metrix
    DBA Metrix Solutions предоставляет удаленного администратора базы данных (DBA), который несет ответственность за внедрение, обслуживание, настройку, восстановление базы данных, а также другие..

    Начало работы с Блум
    Обзор и Codelab для генерации текста с помощью Bloom Оглавление Что такое Блум? Некоторые предостережения Настройка среды Скачивание предварительно обученного токенизатора и модели..

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..