Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.78/9: Рейтинг темы: голосов - 9, средняя оценка - 4.78
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88

Оптимизация алгоритма

20.03.2021, 17:18. Показов 2122. Ответов 42

Студворк — интернет-сервис помощи студентам
Добрый день уважаемые фоумчане.

Как-то давеча я создавал тему на форуме http://www.cyberforum.ru/cpp-b... 65826.html, в которой уважаемый L0M помог мне с алгоритмом написания нарезчика бит.

В данный момент, проведя эксперименты и тесты, я понял что работает нарезчик достаточно медленно (~ +- 32 сек на массив unsigned char на 2 000 000 000 элементов, ~ +- 76 сек на массив unsigned short на 2 000 000 000 элементов и т.д.)

Собственно я и решил после этого что-то своё написать в надежде что битовые смещения работают побыстрее битовых масок (с учетом того, что в отличии от масок битовых смещениями я смогу получать сразу перечень данных), но как-то быстрее не стало, а только медленнее.

Что делает нарезчик:
- принимать в себя массив указателей или указатель на вектор произвольного целочисленного типа данных и порядок бит (прямой - старший бит становится младшим, обратный - классический машинный вариант).
- перепрыгивать через N бит.
- дописывать биты (с учетом порядка бит) в конец послупившего буфера N бит, если эти N бит вмещаются в тип данных буфера.
- остальной функционал не важен - просто баловство.

Прошу помощи в этом деле, может быть я где-то был не прав при написании или что-то ещё. Мне бы секунд до 10 - 20 при любых результатах...

Вот исходники нарезчика, алгоритм которого любезно предоставил уважаемый L0M:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
    /*!
     * \class   BitsSlice
     * \brief   Битовый нарезчик данных.
     * \details ---
     */
    template <typename SourceDataType>
    class BitsSlice
    {
    private:
        /*!
         * \enum    SourceType
         * \brief   Перечисление с внутренними флагами входящих ресурсов для чтения.
         * \details ---
         */
        enum SourceType
        {
            VECTOR   = 1, ///< STL вектор.
            PTRARRAY = 2  ///< Указатель на данные.
        };
 
        SourceDataType     SequenceComponent; ///< Элемент STL вектора/массива указателей.
        unsigned long long int  CurrentIndex; ///< Индекс текущего элемента.
        std::vector<SourceDataType>  *Vector; ///< Указатель на ресурс STL вектора.
        SourceDataType             *PtrArray; ///< Указатель на данные.
        unsigned long long int          Size; ///< Размер ресурса.
        SourceType                      Flag; ///< Флаг вида ресурса.
        unsigned long long int      SizeBits; ///< Размер типа данных в битах.
        unsigned long long int BitIndexInSeq; ///< Битовый индекс текущего элемента.
        bool                           Order; ///< Порядок бит(FALSE - слева направо, TRUE - справа налево).
 
    public:
        /*!
         * \fn      BitsSlice
         * \brief   Конструктор по умолчанию.
         * \details Удален.
         */
        BitsSlice() = delete;
        /*!
         * \fn      BitsSlice
         * \brief   Конструктор копирования.
         * \details Удален.
         * \param   Object - объект класса.
         */
        BitsSlice(const BitsSlice<SourceDataType> &Object) = delete;
        /*!
         * \fn      BitsSlice
         * \brief   Конструктор заполнения объекта.
         * \details Выполняет заполнение объекта с помощью ресурса представленного вектором STL.
         * \param   VectorData - STL вектор.
         * \param   BitOrder   - порядок бит.
         */
        BitsSlice(std::vector<SourceDataType> *VectorData, bool BitOrder = false);
        /*!
         * \fn      BitsSlice
         * \brief   Конструктор заполнения объекта.
         * \details Выполняет заполнение объекта с помощью ресурса представленного указателем на данные.
         * \param   PtrArrayData - указатель на данные.
         * \param   SizeArray    - количество данные в указателе.
         * \param   BitOrder     - порядок бит.
         */
        BitsSlice(SourceDataType *PtrArrayData, const unsigned long long int SizeArray, bool BitOrder = false);
        /*!
         * \fn      ~BitsSlice
         * \brief   Деструктор.
         * \details ---
         */
       ~BitsSlice();
        /*!
         * \fn      JumpOverBeats
         * \brief   Перепрыгнуть на N бит вперед.
         * \details ---
         * \param   NumberOfBits - количество бит.
         * \return  bool         - TRUE - успешное выполнение функции.
         */
        bool JumpOverBeats(unsigned long long int NumberOfBits);
        /*!
         * \fn      CutBits
         * \brief   Отрезать N бит в буффер. Данные ресурса не уничтожаются.
         * \details ---
         * \param   Buffer       - ссылка на буфер.
         * \param   NumberOfBits - количество бит.
         * \return  bool         - TRUE - успешное выполнение функции.
         */
        template<typename BufferDataType>
        bool CutBits(BufferDataType &Buffer, unsigned long long int NumberOfBits);
    };
 
    template <typename SourceDataType>
    BitsSlice<SourceDataType>::BitsSlice(std::vector<SourceDataType> *VectorData, bool BitOrder)
    : SequenceComponent(0),
      CurrentIndex(1),
      Vector(VectorData),
      PtrArray(nullptr),
      Size(0),
      Flag(VECTOR),
      SizeBits(sizeof(SourceDataType) * 8u),
      BitIndexInSeq(sizeof(SourceDataType) * 8u),
      Order(BitOrder),
      BitBuffer("")
    {
        this->Size = this->Vector->size();
        this->SequenceComponent = this->Vector->at(0);
    }
 
    template <typename SourceDataType>
    BitsSlice<SourceDataType>::BitsSlice(SourceDataType *PtrArrayData, const unsigned long long int SizeArray, bool BitOrder)
    : SequenceComponent(0),
      CurrentIndex(1),
      Vector(nullptr),
      PtrArray(PtrArrayData),
      Size(SizeArray),
      Flag(PTRARRAY),
      SizeBits(sizeof(SourceDataType) * 8u),
      BitIndexInSeq(sizeof(SourceDataType) * 8u),
      Order(BitOrder),
      BitBuffer("")
    {
        this->SequenceComponent = this->PtrArrayData[0];
    }
 
    template <typename SourceDataType>
    BitsSlice<SourceDataType>::~BitsSlice()
    {
        this->SequenceComponent = 0;
        this->CurrentIndex      = 0;
        this->Vector            = nullptr;
        this->PtrArray          = nullptr;
        this->Size              = 0;
        this->SizeBits          = 0;
        this->BitIndexInSeq     = 0;
        this->BitBuffer         = "";
    }
 
    template <typename SourceDataType>
    bool BitsSlice<SourceDataType>::JumpOverBeats(unsigned long long int NumberOfBits)
    {
        if (NumberOfBits == 0)
            return true;
 
        else
        if ( !(NumberOfBits ^ BitIndexInSeq) )
        {
            this->BitIndexInSeq = 0;
            return true;
        }
        if (NumberOfBits < this->BitIndexInSeq)
        {
            this->BitIndexInSeq -= NumberOfBits;
            return true;
        }
        else
        {
            while(NumberOfBits > this->BitIndexInSeq)
            {
                if (Size >= CurrentIndex + 1)
                {
                    NumberOfBits -= this->BitIndexInSeq;
                    ++this->CurrentIndex;
                    this->BitIndexInSeq = this->SizeBits;
                }
                else
                    return false;
            }
 
            this->BitIndexInSeq -= NumberOfBits;
 
            switch(this->Flag)
            {
                case VECTOR:
                {
                    SequenceComponent = this->Vector->at(this->CurrentIndex);
                    break;
                }
                case PTRARRAY:
                {
                    SequenceComponent = this->PtrArray[this->CurrentIndex];
                    break;
                }
            }
            return true;
        }
    }
 
    template<typename SourceDataType>
    template<typename BufferDataType>
    bool BitsSlice<SourceDataType>::CutBits(BufferDataType &Buffer, unsigned long long int NumberOfBits)
    {
        if ((sizeof(BufferDataType) * 8u) < NumberOfBits || NumberOfBits == 0)
            return false;
 
        Buffer = 0;
        SourceDataType Mask = 0;
 
        while (NumberOfBits--)
        {
            Buffer <<= 1;
            if (this->BitIndexInSeq == 0)
            {
                if (!(this->CurrentIndex ^ this->Size) || (this->CurrentIndex > this->Size))
                    return false;
 
                switch(Flag)
                {
                    case VECTOR:
                    {
                        SequenceComponent = this->Vector->at(this->CurrentIndex);
                        break;
                    }
                    case PTRARRAY:
                    {
                        SequenceComponent = this->PtrArray[this->CurrentIndex];
                        break;
                    }
                }
                this->CurrentIndex++;
                this->BitIndexInSeq = this->SizeBits;
            }
            if (Order)
                Mask = 1 << (SizeBits - BitIndexInSeq);
            else
                Mask = 1 << (BitIndexInSeq - 1);
            Buffer |= (SequenceComponent & Mask) ? 1 : 0;
            --BitIndexInSeq;
        }
        return true;
    }
вот нарезчик который написал уже я:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    template <typename SourceDataType>
    class BitsSlice
    {
    private:
        /*!
         * \enum    SourceType
         * \brief   Перечисление с внутренними флагами входящих ресурсов.
         * \details ---
         */
        enum SourceType
        {
            Vector   = 1, ///< STL вектор.
            PtrArray = 2  ///< Указатель на данные.
        };
 
        SourceDataType              _sequenceComponent; ///< Элемент STL вектора/массива указателей.
        unsigned long long int           _currentIndex; ///< Индекс текущего элемента.
        std::vector<SourceDataType>           *_vector; ///< Указатель на ресурс STL вектора.
        SourceDataType                      *_ptrArray; ///< Указатель на данные.
        unsigned long long int                   _size; ///< Размер ресурса.
        SourceType                       _flagResource; ///< Флаг вида ресурса.
        unsigned int                       _sizeOfBits; ///< Размер типа данных в битах.
        unsigned int           _bitInSequenceComponent; ///< Остаток бит на текущий раунд.
        bool                                 _bitOrder; ///< Порядок бит(FALSE - слева направо, TRUE - справа налево).
 
    public:
        /*!
         * \fn      BitsSlice
         * \brief   Конструктор по умолчанию.
         * \details Удален.
         */
        BitsSlice() = delete;
        /*!
         * \fn      BitsSlice
         * \brief   Конструктор копирования.
         * \details Удален.
         * \param   object - объект класса.
         */
        BitsSlice(const BitsSlice<SourceDataType> &object) = delete;
        /*!
         * \fn      BitsSlice
         * \brief   Конструктор заполнения объекта.
         * \details Выполняет заполнение объекта с помощью ресурса представленного вектором STL.
         * \param   vectorArray - STL вектор.
         * \param   bitOrder    - порядок бит.
         */
        BitsSlice(std::vector<SourceDataType> *vectorArray, bool bitOrder = false);
        /*!
         * \fn      BitsSlice
         * \brief   Конструктор заполнения объекта.
         * \details Выполняет заполнение объекта с помощью ресурса представленного указателем на данные.
         * \param   ptrArray     - указатель на данные.
         * \param   arraySize    - количество данные в указателе.
         * \param   bitOrder     - порядок бит.
         */
        BitsSlice(SourceDataType *ptrArray, const unsigned long long int arraySize, bool bitOrder = false);
        /*!
         * \fn      ~BitsSlice
         * \brief   Деструктор.
         * \details ---
         */
       ~BitsSlice();
        /*!
         * \fn      jumpOverBeats
         * \brief   Перепрыгнуть на N бит вперед.
         * \details ---
         * \param   numberOfBits - количество бит.
         * \return  bool         - TRUE - успешное выполнение функции.
         */
        bool jumpOverBeats(unsigned int numberOfBits);
        /*!
         * \fn      cutBits
         * \brief   Отрезать N бит в буффер. Данные ресурса не уничтожаются.
         * \details ---
         * \param   buffer       - ссылка на буфер.
         * \param   numberOfBits - количество бит.
         * \return  bool         - TRUE - успешное выполнение функции.
         */
        template<typename BufferDataType>
        bool cutBits(BufferDataType &buffer, unsigned int numberOfBits);
 
    private:
        /*!
         * \fn      getCurrentSequenceComponent
         * \brief   Получить элемент STL вектора/массива указателей по текущему индексу.
         * \details ---
         * \return  bool - TRUE - успешное выполнение функции.
         */
        bool getCurrentSequenceComponent();
    };
 
    template <typename SourceDataType>
    BitsSlice<SourceDataType>::BitsSlice(std::vector<SourceDataType> *vectorArray, bool bitOrder)
    : _sequenceComponent(0),
      _currentIndex(0),
      _vector(vectorArray),
      _ptrArray(nullptr),
      _size(0),
      _flagResource(Vector),
      _sizeOfBits(sizeof(SourceDataType) * 8u),
      _bitInSequenceComponent(sizeof(SourceDataType) * 8u),
      _bitOrder(bitOrder),
      _bitBuffer("")
    {
        this->_size              = this->_vector->size();
        this->_sequenceComponent = this->_vector->at(0);
    }
 
    template <typename SourceDataType>
    BitsSlice<SourceDataType>::BitsSlice(SourceDataType *ptrArray, const unsigned long long int arraySize, bool bitOrder)
    : _sequenceComponent(0),
      _currentIndex(0),
      _vector(nullptr),
      _ptrArray(ptrArray),
      _size(arraySize),
      _flagResource(PtrArray),
      _sizeOfBits(sizeof(SourceDataType) * 8u),
      _bitInSequenceComponent(sizeof(SourceDataType) * 8u),
      _bitOrder(bitOrder),
      _bitBuffer("")
    {
        this->_sequenceComponent = this->_ptrArray[0];
    }
 
    template <typename SourceDataType>
    BitsSlice<SourceDataType>::~BitsSlice()
    {
        this->_sequenceComponent      = 0;
        this->_currentIndex           = 0;
        this->_vector                 = nullptr;
        this->_ptrArray               = nullptr;
        this->_size                   = 0;
        this->_sizeOfBits             = 0;
        this->_bitInSequenceComponent = 0;
        this->_bitBuffer              = "";
    }
 
    template <typename SourceDataType>
    bool BitsSlice<SourceDataType>::jumpOverBeats(unsigned int numberOfBits)
    {
        if (numberOfBits <= this->_bitInSequenceComponent)
        {
            this->_bitInSequenceComponent -= numberOfBits;
            return true;
        }
        else
        {
            numberOfBits -= this->_bitInSequenceComponent;
 
            unsigned int сoefficient = numberOfBits / this->_sizeOfBits;
 
            numberOfBits -= сoefficient * this->_sizeOfBits;
            this->_currentIndex += сoefficient + 1;
            this->_bitInSequenceComponent = this->_sizeOfBits - numberOfBits;
 
            return this->getCurrentSequenceComponent();
        }
    }
 
    template<typename SourceDataType>
    template<typename BufferDataType>
    bool BitsSlice<SourceDataType>::cutBits(BufferDataType &buffer, unsigned int numberOfBits)
    {
        if ((sizeof(BufferDataType) * 8u) < numberOfBits || !numberOfBits)
            return false;
 
        unsigned int bitShiftLeft     = 0;
        unsigned int bitShiftRight    = 0;
 
        while(numberOfBits)
        {
            if (!this->_bitInSequenceComponent)
            {
                this->_bitInSequenceComponent = this->_sizeOfBits;
                ++this->_currentIndex;
            }
 
            if (!this->getCurrentSequenceComponent())
                return false;
 
            unsigned int bitCountsInRound =
                                 this->_bitInSequenceComponent <= numberOfBits
                               ? this->_bitInSequenceComponent
                               : numberOfBits;
 
            if (this->_bitOrder)
            {
                /* обратный порядок */
                bitShiftLeft  = this->_bitInSequenceComponent - bitCountsInRound;
                bitShiftRight = this->_sizeOfBits - bitCountsInRound;
            }
            else
            {
                /* прямой порядок */
                bitShiftLeft  = this->_sizeOfBits - this->_bitInSequenceComponent;
                bitShiftRight = this->_sizeOfBits - bitCountsInRound;
            }
 
            this->_sequenceComponent <<= bitShiftLeft;
            this->_sequenceComponent >>= bitShiftRight;
 
            buffer                       <<= bitCountsInRound;
            buffer                        |= this->_sequenceComponent;
            this->_bitInSequenceComponent -= bitCountsInRound;
            numberOfBits                  -= bitCountsInRound;
 
            if (this->_bitOrder && bitCountsInRound > 1)
            {
                bool flag      = bitCountsInRound % 2;
                bool flagBegin = false;
                bool flagEnd   = false;
                for (unsigned int index = 0; --bitCountsInRound; ++index)
                {
                    flagBegin = (buffer & (1 << index) ? true : false);
                    flagEnd   = (buffer & (1 << bitCountsInRound) ? true : false);
 
                    if ((flagBegin && !flagEnd) || (!flagBegin && flagEnd))
                    {
                        buffer ^= (1 << bitCountsInRound);
                        buffer ^= (1 << index);
                    }
 
                    if (!( (flag ? bitCountsInRound + 1 : bitCountsInRound) ^ (index + 1)))
                        break;
                }
            }
        }
        return true;
    }
 
    template <typename SourceDataType>
    bool BitsSlice<SourceDataType>::getCurrentSequenceComponent()
    {
        if (this->_currentIndex >= this->_size)
            return false;
 
        switch(this->_flagResource)
        {
            case Vector:
                this->_sequenceComponent = this->_vector->at(this->_currentIndex);
                break;
 
            case PtrArray:
                this->_sequenceComponent = this->_ptrArray[this->_currentIndex];
                break;
        }
        return true;
    }
замеры времени делал :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Timer
{
private:
    using clock_t = std::chrono::high_resolution_clock;
    using second_t = std::chrono::duration<double, std::ratio<1> >;
 
    std::chrono::time_point<clock_t> m_beg;
 
public:
    Timer() : m_beg(clock_t::now())
    {
    }
 
    void reset()
    {
        m_beg = clock_t::now();
    }
 
    double elapsed() const
    {
        return std::chrono::duration_cast<second_t>(clock_t::now() - m_beg).count();
    }
};
Заранее спасибо.

P.S.: Самое забавное что под дебагом мой нарезчик побыстрее будет (оптимизация творит чудеса...), а вот в релизе всё становится печально, результаты фиксированно в приделах 110 сек...

Добавлено через 2 часа 42 минуты
Сделал кое-какие изменения во втором нарезчике (который сам писал), а именно в функции cutBits, которая и требует оптимизации:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
        /*!
         * \fn      cutBits
         * \brief   Отрезать N бит в буффер. Данные ресурса не уничтожаются.
         * \details ---
         * \param   buffer       - ссылка на буфер.
         * \param   numberOfBits - количество бит.
         * \return  bool         - TRUE - успешное выполнение функции.
         */
        template<typename BufferDataType>
        bool cutBits(BufferDataType &buffer, unsigned int numberOfBits)
        {
            if ((sizeof(BufferDataType) * 8u) < numberOfBits || !numberOfBits)
                return false;
 
            unsigned int bitShiftLeft  = 0;
            unsigned int bitShiftRight = 0;
 
            while(numberOfBits)
            {
                if (!this->_bitInSequenceComponent)
                {
                    this->_bitInSequenceComponent = this->_sizeOfBits;
                    ++this->_currentIndex;
                    if (!this->getCurrentSequenceComponent())
                        return false;
                }
 
                unsigned int bitCountsInRound =
                                     this->_bitInSequenceComponent <= numberOfBits
                                   ? this->_bitInSequenceComponent
                                   : numberOfBits;
 
                if (this->_bitOrder)
                {
                    /* обратный порядок */
                    bitShiftLeft  = this->_bitInSequenceComponent - bitCountsInRound;
                    bitShiftRight = this->_sizeOfBits - bitCountsInRound;
 
                    (buffer <<= bitCountsInRound) |= (this->_sequenceComponent << bitShiftLeft) >> bitShiftRight;
                    this->_bitInSequenceComponent -= bitCountsInRound;
                    numberOfBits                  -= bitCountsInRound;
 
                    if (bitCountsInRound > 1)
                    {
                        bool flag      = bitCountsInRound % 2;
                        bool flagBegin(false);
                        bool flagEnd(false);
                        for (unsigned int index = 0; --bitCountsInRound; ++index)
                        {
                            flagBegin = buffer & (1 << index);
                            flagEnd   = buffer & (1 << bitCountsInRound);
 
                            if ((flagBegin && !flagEnd) || (!flagBegin && flagEnd))
                            {
                                buffer ^= 1 << bitCountsInRound;
                                buffer ^= 1 << index;
                            }
 
                            if (!( (flag ? bitCountsInRound + 1 : bitCountsInRound) ^ (index + 1)))
                                break;
                        }
                        /*
                        bool flag      = bitCountsInRound % 2;
                        bool flagBegin = false;
                        bool flagEnd   = false;
                        for (unsigned int index = 0; --bitCountsInRound; ++index)
                        {
                            flagBegin = buffer & (1 << index);
                            flagEnd   = buffer & (1 << bitCountsInRound);
 
                            if ((flagBegin && !flagEnd) || (!flagBegin && flagEnd))
                            {
                                buffer ^= (1 << bitCountsInRound);
                                buffer ^= (1 << index);
                            }
 
                            if (!( (flag ? bitCountsInRound + 1 : bitCountsInRound) ^ (index + 1)))
                                break;
                        }
                        */
                    }
 
                    continue;
                }
 
                /* прямой порядок */
                bitShiftLeft  = this->_sizeOfBits - this->_bitInSequenceComponent;
                bitShiftRight = this->_sizeOfBits - bitCountsInRound;
 
                (buffer <<= bitCountsInRound) |= (this->_sequenceComponent << bitShiftLeft) >> bitShiftRight;
                this->_bitInSequenceComponent -= bitCountsInRound;
                numberOfBits                  -= bitCountsInRound;
 
                continue;
            }
            return true;
        }
Буду рад любым предложениям по оптимизации.
Спасибо.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.03.2021, 17:18
Ответы с готовыми решениями:

Оптимизация алгоритма
Условие: Дана выборка (X_i, Y_i)_{i=1}^N. Предполагается, что она была построена по следующему закону: \begin{cases} Y=\beta \xi...

Оптимизация алгоритма
#include&lt;iostream&gt; #include&lt;stdlib.h&gt; #include&lt;time.h&gt; #include&lt;iomanip&gt; using namespace std; #define jaba for(i=0; i&lt;k; i++)...

Оптимизация алгоритма
Всем привет. Если кто-то сможет оптимизировать &quot;это&quot;, то я отблагодарю его материально. uint32_t a0 = ps*26 + ps*51 + ps*102 + ps*51 +...

42
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
22.03.2021, 16:54
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Aringot Посмотреть сообщение
по поводу комбинирования вариантов - наверное это не самая лучшая идея, она ведь повлечет появления ветвления уже на начальных этапах
У вас появится только одно ветвление в самом начале cutBits(). На сколько такое ветвление будет тормозить - это зависит от режима боевго использования. Нужно проверять.

У вас планируется numberBits постоянным для каждого заплыва (как сейчас у вас это реализовано в тестовой программе)? Или оно будет плавать от 1 до какого-то предела при каждом вызове cutBits()? Если будет плавать, попробуйте ещё протестировать с рандомным значением numberBits для каждого вызова cutBits().

Если numberBits постоянно для наждого массива данных, то параллелится достаточно просто. Массив "пилится" на куски, кратные НОК(numberBits, sizeof(array_type) * 8) / sizeof(array_type) * 8. Каждый кусок отдаётся на обработку в отдельный поток. Сколько будет выходных данных для каждого куска - тоже вычисляется. Значит смещение в выходном буфере тоже считается.

На уровне идеи: ещё есть векторные инструкции SIMD: всякие SSE, AVX и пр. Может в эту сторону можно подумать.
0
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 17:47  [ТС]
Значение numberBits при каждом выполнение будет рандомным, т.к. этот класс направлен на распиливание сырого массива растровых данных формата TIFF, а в соответствии со спецификацией данные могут быть разными, в диапазоне от 1 - 64 бит на один цветовой канал изображения.
По поводу фиксированности - тут тоже не все однозначно, есть вероятность встретить растры с разным количеством бит на канал, поэтому вариант с разделением на равные куски не кажется мне удачным.

Добавлено через 42 минуты
По поводу правдивости моего высказывания о разных значениях количества бит на компонент - Ссылка

...
LibTiff does not support different BitsPerSample values for different components.
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
22.03.2021, 18:33
Aringot, а почему вы не используете какую-нибудь опенсорсную библиотеку для работы с TIFF. Неужели нет подходящей? Или вы как раз решили написать такую?
0
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 18:39  [ТС]
Как раз решил написать, и для работы, и для себя, ну и для защиты диплома (так сказать актуальность выражена в возможности читать файлы с произвольным количеством бит на канал изображения). И именно для этого мне и нужен битовый нарезчик дабы обойти это ограничение, которое присутствует в LibTiff, ну и плюсом в LibTiff нет удобного интерфейса для работы с содержимым файла.

Собственно вот такие дела.
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
22.03.2021, 19:38
Цитата Сообщение от Aringot Посмотреть сообщение
Как раз решил написать
Безумству храбрых поём мы славу! (с) М.Горький

Посмотрел я на краткое описание TIFF в Википедии... Но, как говорится, вода камень точит...

При чтении "по диагонали" зацепился за один раздельчик:
Strips
A baseline TIFF image is composed of one or more strips. A strip (or band) is a subsection of the image composed of one or more rows. Each strip may be compressed independently of the entire image, and each begins on a byte boundary. If the image height is not evenly divisible by the number of rows in the strip, the last strip may contain fewer rows. If strip definition tags are omitted, the image is assumed to contain a single strip.
Т.е. изображение - это не многогигабайтный поток сырых битов, а последовательность вполне разумных кусков известных размеров (StripByteCounts), выровненных на границу байта. Вот вам сразу возможность для распараллеливания. Это раз.

В полоске (aka стрипе) данные скомпрессированы. (Компрессоры/декомпрессоры всех задекларированных в стандарте TIFF форматов сжатия вы тоже будете сами писать? Или всё-таки воспользуетесь готовыми решениями?). Вопрос: после декомпрессии данные по каналам тоже будут в виде потока бит? Или всё же будут выровнены по границе байта? Это два.

Это я к тому, что может можно обойтись малой кровью в плане cutBits()?

PS. Я ни разу не специалист по TIFF и вообще по обработке изображений, а также по алгоритмам компрессии.
0
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 19:56  [ТС]
Да, Вы правы, данные растра выравнены до границы байта. Но есть нюанс, заключается он в том, что есть два варианта расположения данных в файле (за это отвечает тег PlanarConfiguration[284]):
- данные лежат подряд (на примере с цветовым пространством RGB - ...RGBRGBRGB...).
- данные лежат поканально(на примере с цветовым пространством RGB - ...RRR... ...GGG... ...BBB...).

А данные я буду возвращать пользователю в объектах (спецификация определяет "Полосы" и "Плитки"(Тайлы)), которые уже будут содержать в себе данные нарезанные поканально и разложеные по минимальной единице - байту

Ну и соответственно такое архитектурное решение накладывает ограничения.

В теории я мог бы многопоточно читать данные, но возникнут сложности с размещением данных в моих объектах.
Пока реализую так как задумал, точнее перепишу что наваял в черновом варианте.

Добавлено через 7 минут
По поводу схем распаковки, думаю писать их сам, не очень хотелось бы тянуть за сабой кучу всего, да и при этом подавляющее большинство данных которые я буду читать запакованы LZW и PackBits. Вторую схему я уже накидал, вот к примеру:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
bool UnpackPackBits(signed char *PackString, unsigned long long int Size, std::vector<char> &UnpackString)
{
    signed int Length = 0;
    for (unsigned long long int IndexPackString = 0; IndexPackString < Size; ++IndexPackString)
    {
        if (PackString[IndexPackString] == -128)
                continue;
 
        if (PackString[IndexPackString] >= -127 && PackString[IndexPackString] < 0)
        {
            Length = (-PackString[IndexPackString++]) + 1;
            //++IndexPackString;
            UnpackString.insert(UnpackString.end(), static_cast<unsigned long long int>(Length), PackString[IndexPackString]);
        }
        else if (PackString[IndexPackString] >= 0)
        {
            Length = PackString[IndexPackString++] + 1;
            //++IndexPackString;
            UnpackString.insert(UnpackString.end(), PackString + IndexPackString,
                                                    PackString + (IndexPackString + Length));
            IndexPackString += Length - 1;
        }
        else
            return false;
    }
    return true;
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
22.03.2021, 19:59
Цитата Сообщение от Aringot Посмотреть сообщение
В теории я мог бы многопоточно читать данные, но возникнут сложности с размещением данных в моих объектах.
Не думаю, что там возникнут сложности непреодолимой силы. Размеры все известны. Сколько данных должно получиться после распаковки - тоже. Всегда можно зарезервировать необходимое место и вычислить смещение для сохранения данных. Вроде так. Впрочем это зависит от вашего архитектурного решения, которого я не знаю. Так что вам виднее.
0
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 20:03  [ТС]
Да, тут вы правы, если совсем честно, то с многопоточностью у меня не очень, может как-нибудь руки дойдут, но не сейчас, сроки поджимают.
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
22.03.2021, 20:25
Цитата Сообщение от Aringot Посмотреть сообщение
Вторую схему я уже накидал
Не нравится мне ваша реализация...

Во-первых, чисто технически. Почему функция возвращает bool? "Не шмогла"?

Далее, смотрим if-ы в цикле: -128 - понятно, от -127 до 0 - понятно, от 0 и больше - понятно. Строки 23-24 в каком случае будут выполнены?

Цикл for с модификацией переменной цикла внутри тела цикла - не лучшая идея. Цикл while с явным инкрементом IndexPackString в нужных местах здесь будет уместнее.

Во-вторых, std::vector.insert() может вызывать перераспределение памяти. Это дорогая операция. Поэтому, если вам известно количество распакованных данных (по размеру стрипа/тайла/строки/изображения), то лучше заранее через std::vector.resize() выделить необходимое место. А данные потом копировать через обращение по индексу или вообще вызовом memset или memcpy.

Добавлено через 1 минуту
Цитата Сообщение от Aringot Посмотреть сообщение
Да, тут вы правы, если совсем честно, то с многопоточностью у меня не очень, может как-нибудь руки дойдут, но не сейчас, сроки поджимают.
Это другой вопрос. Теоретически возможность распараллелить обработку есть.
0
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 20:32  [ТС]
По первому, да, именно так - угадали.
По второму, вообще не выполнятся, работа ведь происходит со знаковым целым 8 битным.
На счет выделения, да, разумно.

Спасибо что указали на косяки, давно эту функцию не смотрел.
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
22.03.2021, 20:46
Цитата Сообщение от Aringot Посмотреть сообщение
По первому, да, именно так - угадали.
По второму, вообще не выполнятся, работа ведь происходит со знаковым целым 8 битным.
И если соединить первое со вторым...
0
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 20:52  [ТС]
то возвращаемое значение вообще бесмысслено делать для этой функции, либо если есть нюансы связанные с проверкой длины исходного массива, то в таком случае нужно.
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
22.03.2021, 21:01
Цитата Сообщение от Aringot Посмотреть сообщение
вообще бесмысслено делать для этой функции, либо если есть нюансы
В правильном направлении мыслите, товарищ
1
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 21:03  [ТС]
И снова благодарю Вас за мудрые наставления!
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
22.03.2021, 21:24
Aringot, а разве из поста про который упоминалось в шапке, не видно о том что структура файла байтовая.
И из отрывка я не понял что за формат такйо при котором нужно работать над битами как над отдельной структурой.
?

Добавлено через 1 минуту
Я хочу сказать что такие манипуляции делаются только при чтении/записи файла, но не при обработке.
0
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 21:26  [ТС]
SmallEvil, теговая структура файла байтовая, но данные растра могут иметь размер цветовой компоненты которая меньше одного байта.

Так я файлы данного формата собираюсь читать и отрисовывать, возможно писать(но это не точно).
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
22.03.2021, 21:32
Aringot, понятно, что мешает обойтись без нарезки ?
економия озу ?
или это алгоритм декомпрессии ?
0
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 21:38  [ТС]
В растре данные идут подряд, то есть без выравнивания до байта, выравнивание есть только между концом и началом новой строки изображения.

Как я уже упоминал ранее, формат поддерживает различное количество бит на цветовую компоненту (например: 4,5,4 бит для RGB или 3,4,4 бит и т.д.), а идея в том, что бы эти данные разложить в приделах минимально вместимого типа данных.

Таким образом речь о какой-либо экономии озу не идёт, экономиться она будет с помощью произвольного чтения по номеру объекта изображения (строки/тайла), а не чтения целого изображения.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
22.03.2021, 21:40
Цитата Сообщение от Aringot Посмотреть сообщение
Как я уже упоминал ранее, формат поддерживает различное количество бит на цветовую компоненту
но не в одном же изображении ?

ладно, завтра ознакомлюсь с форматом .
дайте спецификацию, точное название формата.
0
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88
22.03.2021, 21:44  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
но не в одном же изображении ?
В приделах одного изображения.
Формат TIFF
Явное указание на то, что я говорил:
Aware Systems
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
22.03.2021, 21:44
Помогаю со студенческими работами здесь

Оптимизация алгоритма
Если ввести очень большое значение желаемой суммы вклада примерно 10 в 9 степени , то работа алгоритма затягивается, как можно...

Оптимизация алгоритма быстрого поиска
Допустим есть строка: &quot;Съешь ещё этих мягких французских булок, да выпей же чаю&quot;,и есть массив готовых строк, к примеру {...

Оптимизация алгоритма вычисления определителя матрицы
Здравствуйте! Написал я давеча программку, которая считает определитель. Только вот беда - он не считает определители матриц выше 10...

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

Оптимизация алгоритма перемножения двух матриц
Здравствуйте, нужна помощь. Есть 2 матрицы, нужно их перемножить так, что бы алгоритм выполнялся со скорость O(n) и O(log(n))


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 31.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 31.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 30.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru