Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
Valeryn
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 264
1

Оптимизация выполнение операторов

04.10.2017, 22:28. Просмотров 766. Ответов 9
Метки нет (Все метки)

Есть такой код реализации матрицы
Кликните здесь для просмотра всего текста
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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
namespace Nero {
 
typedef __nreal nreal;
 
template<typename _Tp>
using VectorMatrix = std::vector<std::vector<_Tp> >;
 
template<typename _Tp>
struct Sum {
    inline _Tp operator() (const _Tp &a, const _Tp &b) {
        return a+b;
    }
};
 
template<typename _Tp>
struct Diff {
    inline _Tp operator() (const _Tp &a, const _Tp &b) {
        return a-b;
    }
};
 
template<typename _Tp>
struct Comp {
    inline _Tp operator() (const _Tp &a, const _Tp &b) {
        return a*b;
    }
};
 
template<typename _Tp>
struct Part {
    inline _Tp operator() (const _Tp &a, const _Tp &b) {
        return a*b;
    }
};
 
template<typename _Tp>
struct Add {
    inline _Tp &operator() (_Tp &a, const _Tp &b) {
        return a += b;
    }
};
 
template<typename _Tp>
struct Ded {
    inline _Tp &operator() (_Tp &a, const _Tp &b) {
        return a -= b;
    }
};
 
template<typename _Tp>
struct MultiBy {
    inline _Tp &operator() (_Tp &a, const _Tp &b) {
        return a *= b;
    }
};
 
template<typename _Tp>
struct DevideBy {
    inline _Tp &operator() (_Tp &a, const _Tp &b) {
        return a /= b;
    }
};
 
template<typename _Tp>
struct Increment {
    inline _Tp &operator() (_Tp &a) {
        return ++a;
    }
};
 
template<typename _Tp>
struct Dicrement {
    inline _Tp &operator() (_Tp &a) {
        return --a;
    }
};
 
template<typename _Tp = nreal>
class Matrix : public std::vector<_Tp>
{
private:
    ///exceptions
    void _exception_out_of_range_(size_t size) const
    {
        if (this->size() < size)
            throw std::out_of_range("Matrix _exception_out_of_range_ Matrix size: " + std::to_string(this->size()) + "<" + std::to_string(size));
    }
 
    void _exception_matrix_value_(const size_t &_rows, const size_t &_cols) const
    {
        if (_rows > m_rows || _cols > m_cols) {
            throw std::length_error("Matrix _exception_matrix_value_ this Matrix size [" + std::to_string(m_rows) + "][" + std::to_string(m_cols) + "] " +
                                    "\n index value[" + std::to_string(m_rows) + "][" + std::to_string(m_cols) + "]");
        }
    }
 
    ///end exceptions
 
    ///chek
    static_assert(std::is_arithmetic<_Tp>::value, "Matrix type is not arithmetic");
 
public:
    Matrix() : m_rows(0), m_cols(0),
        std::vector<_Tp>(0)
    {}
 
    Matrix(const size_t &_cols) :
        std::vector<_Tp>(_cols), m_rows(1), m_cols(_cols)
    {}
 
    Matrix(const size_t &_rows, const size_t &_cols) :
        std::vector<_Tp>(_cols * _rows)
    { m_rows = _rows;  m_cols = _cols; }
 
    Matrix(const Matrix &copy) :
        std::vector<_Tp>(copy)
    { m_rows = copy.rows(); m_cols = copy.cols(); }
 
    Matrix(_Tp *_data, const size_t &_rows, const size_t &_cols) :
        Matrix(_rows, _cols)
    {
        if (this->size() > 0)
            std::memcpy(this->data(), _data, _rows * _cols * sizeof(_Tp));
    }
 
    Matrix(std::initializer_list<_Tp> l, const size_t &_rows, const size_t &_cols) :
        std::vector<_Tp>(l)
    {
        m_rows = _rows;
        m_cols = _cols;
        this->resize(_rows * _cols, 0x0);
    }
 
    Matrix(std::initializer_list<_Tp> l) : Matrix(l, 1, l.size())
    {}
 
    Matrix(std::initializer_list<std::initializer_list<_Tp> > l) :
        std::vector<_Tp>(0)
    {
        m_rows = l.size();
        m_cols = l.begin()->size();
        for (const std::initializer_list<_Tp> &v : l) {
            this->insert(this->end(), v.begin(), v.end());
        }
    }
 
    Matrix(const std::vector<_Tp> &vec, const size_t &_rows, const size_t &_cols) :
        std::vector<_Tp>(vec), m_rows(_rows), m_cols(_cols)
    { this->resize(_rows * _cols, 0x0); }
 
    Matrix(const std::vector<_Tp> &vec) : Matrix(vec, 1, vec.size())
    {}
 
    Matrix(const std::vector<std::vector<_Tp> > &vec) : std::vector<_Tp>(0), m_rows(vec.size()), m_cols(0)
    {
        if (vec.size() > 0) {
            m_cols = vec[0].size();
            for (size_t i = 0; i < vec.size(); i++) {
                this->insert(this->end(), vec[i].begin(), vec[i].end());
            }
        }
    }
 
 
    Matrix &thisReference() const
    {
        return *this;
    }
 
    size_t cols() const
    { return m_cols; }
    size_t rows() const
    { return m_rows; }
 
    void setSize(const size_t &_rows, const size_t &_cols)
    {
        this->resize(m_rows * m_cols);
    }
 
    size_t getSize() const
    { return m_rows * m_cols; }
 
    _Tp *copy() const
    {
        size_t size_ = m_rows * m_cols;
        if (size_ == 0)
            return nullptr;
        _Tp *copyData = new _Tp[size_];
        std::memcpy(copyData, this->data(), size_ * sizeof(_Tp));
        return copyData;
    }
 
    void setValue(const size_t &row, const size_t &col, const nreal &value)
    {
        _exception_matrix_value_(row, col);
        *this[(row * m_cols) + col] = value;
    }
 
    _Tp getValue(const size_t &row, const size_t &col) const
    {
        _exception_matrix_value_(row, col);
        return *this[(row * m_cols) + col];
    }
 
    _Tp getValue(const size_t &index) const
    {
        _exception_out_of_range_(index);
        return *this[index];
    }
 
    _Tp &value(const size_t &row, const size_t &col)
    {
        _exception_matrix_value_(row, col);
        return std::vector<_Tp>::operator[]((row * m_cols) + col);
    }
 
    const _Tp &value(const size_t &row, const size_t &col) const
    {
        _exception_matrix_value_(row, col);
        return std::vector<_Tp>::operator[]((row * m_cols) + col);
    }
 
    _Tp &value(const size_t &index)
    {
        _exception_out_of_range_(index);
        return std::vector<_Tp>::operator[](index);
    }
 
    const _Tp &value(const size_t &index) const
    {
        _exception_out_of_range_(index);
        return std::vector<_Tp>::operator[](index);
    }
 
    size_t getIndex(const size_t &row, const size_t &col) const
    {
        return (row * m_cols) + col;
    }
 
    void clear()
    {
        m_cols = 0;
        m_rows = 0;
        std::vector<_Tp>::clear();
    }
 
    void fill(const _Tp &value)
    {
        std::fill(this->begin(), this->end(), value);
    }
 
    template<typename _Gen>
    void generate(_Gen gen)
    {
        std::generate(this->begin(), this->end(), gen);
    }
 
    Matrix dot(const Matrix &B) const
    {
        return *this ^ B;
    }
 
    inline Matrix transform() const
    {
        size_t n = this->m_rows;
        size_t m = this->m_cols;
        Matrix<_Tp> C(m,n);
 
        for (size_t i = 0; i < m; i++) {
            for (size_t j = 0; j < n; j++) {
                C.value(i, j) = this->value(j, i);
            }
        }
        return C;
    }
 
    inline Matrix &thisTransform()
    {
        size_t n = this->m_rows;
        size_t m = this->m_cols;
        Matrix<_Tp> C(m,n);
 
        for (size_t i = 0; i < m; i++) {
            for (size_t j = 0; j < n; j++) {
                C.value(i, j) = this->value(j, i);
            }
        }
        *this = C;
        return *this;
    }
 
    inline Matrix T() const
    {
        size_t n = this->m_rows;
        size_t m = this->m_cols;
        Matrix<_Tp> C(m,n);
 
        for (size_t i = 0; i < m; i++) {
            for (size_t j = 0; j < n; j++) {
                C.value(i, j) = this->value(j, i);
            }
        }
        return C;
    }
 
    template<class _Predicate, typename _Tp2>
    static inline Matrix _operatorTemplate_MatA_MatB_to_MatC(const Matrix &A, const Matrix<_Tp2> &B, _Predicate per)
    {
        Matrix<_Tp> C(A);
        size_t size = C.size();
        for (size_t i = 0; i < size; ++i)
            C[i] = per(A[i], static_cast<_Tp>(B[i]));
        return C;
    }
 
    template<class _Predicate, typename _Tp2>
    static inline Matrix &_operatorTemplate_MatA_MatB_to_MatA(Matrix &A, const Matrix<_Tp2> &B, _Predicate per)
    {
        size_t size = A.size();
        for (size_t i = 0; i < size; ++i)
            A[i] = per(A[i], static_cast<_Tp>(B[i]));
        return A;
    }
 
    template<class _Predicate, typename _Tp2>
    static inline Matrix _operatorTemplate_MatA_TypeB_to_MatC(const Matrix &A, const _Tp2 &B, _Predicate per)
    {
        Matrix<_Tp> C(A);
        size_t size = C.size();
        for (size_t i = 0; i < size; ++i)
            C[i] = per(A[i], static_cast<_Tp>(B));
        return C;
    }
 
    template<class _Predicate, typename _Tp2>
    static inline Matrix &_operatorTemplate_MatA_TypeB_to_MatA(Matrix &A, const _Tp2 &B, _Predicate per)
    {
        size_t size = A.size();
        for (size_t i = 0; i < size; ++i)
            A[i] = per(A[i], B);
        return A;
    }
 
    template<class _Predicate, typename _Tp2, typename _Tp3>
    static inline Matrix _operatorTemplate_TypeA_MatB_to_MatC(const _Tp2 &A, const Matrix &B, _Predicate per)
    {
        Matrix<_Tp> C(A);
        size_t size = C.size();
        for (size_t i = 0; i < size; ++i)
            C[i] = per(static_cast<_Tp>(A), B[i]);
        return C;
    }
 
    template<typename _Tp2>
    inline Matrix operator*(const Matrix<_Tp2> &B)
    {
        return _operatorTemplate_MatA_MatB_to_MatC(*this, B, Comp<_Tp>());
    }
 
    template<typename _Tp2>
    inline Matrix operator^(const Matrix<_Tp2> &B) const
    {
        size_t m = this->cols();
        size_t l = this->rows();
        size_t n = B.cols();
 
        Matrix C(l, n);
        for (size_t i = 0; i < l; ++i) {
            for (size_t j = 0; j < n; ++j) {
                C.value(i, j) = 0;
                for (size_t r = 0; r < m; ++r) {
                    C.value(i, j) += this->value(i, r) * static_cast<_Tp2>(B.value(r, j));
                }
            }
        }
 
        return C;
    }
 
    template<typename _Tp2>
    inline Matrix operator+(const Matrix<_Tp2> &B) const
    {
        return _operatorTemplate_MatA_MatB_to_MatC(*this, B, Sum<_Tp>());
    }
 
    template<typename _Tp2>
    inline Matrix operator-(const Matrix<_Tp2> &B) const
    {
        return _operatorTemplate_MatA_MatB_to_MatC(*this, B, Diff<_Tp>());
    }
 
    template<typename _Tp2>
    inline Matrix operator/(const Matrix<_Tp2> &B) const
    {
        return _operatorTemplate_MatA_MatB_to_MatC(*this, B, Part<_Tp>());
    }
    inline Matrix operator--(int)
    {
        for (size_t i = 0; i < this->size(); *this[i++]--);
        return *this;
    }
 
    inline Matrix operator++(int)
    {
        for (size_t i = 0; i < this->size(); *this[i++]++);
        return *this;
    }
 
    inline Matrix &operator=(const Matrix &B)
    {
        this->m_cols = B.cols();
        this->m_rows = B.rows();
        std::vector<_Tp>::operator=(B);
        return *this;
    }
 /**Тут еще куча других операторов*/
 
private:
    size_t m_cols = 0;
    size_t m_rows = 0;
 
};
}


Все в принципе в нем хорошо работает, за исключением одного НО!
Каждый оператор умножения, деления, суммы и т.д. вызывают цикл. Во время этих операций матрицы обязаны быть одинакового размера.
Но например при такой операции
C++
1
Matrix<double> A = A * A / A + A;
На каждом шагу будет вызываться цикл.
Сейчас обхожусь костылями в виде отдельных функций
типо
C++
1
2
3
4
5
6
7
8
 auto delta = [&](const Matrix<double> &error, const Matrix<double> &layer) {
        size_t size = layer.size();
        Matrix<double> result(layer.rows(), layer.cols());
        for (size_t i = 0; i < size; ++i) {
            result.value(i) = error.value(i) * (layer.value(i) * (1.0 - layer.value(i)));
        }
        return result;
    };
Что бы обойтись одним циклом для всех операций.
Можно ли как то это оптимизировать в виде операторов.
Или я слишком много хочу?)
0
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.10.2017, 22:28
Ответы с готовыми решениями:

Оптимизация за счёт устранения временных объектов при использовании операторов
Доброго времени суток! Вопрос в следующем: существует совет по оптимизации: &quot;Не создавайте...

Задача с использованием логических операторов и операторов ветвления
Вот вам задачка, чтоб голову поломать :D Вася работает программистом и получает 50$ за каждые...

Что такое "перегрузка операторов"? Каковы принципы работы перегруженных операторов и назначение указателя this
Добрый день . Помогите понять принцип работы перегрузки операторов. объясните пожалуйста в...

Одновременное выполнение двух операторов
Здравствуйте, подскажите, как сделать так чтобы два или более операторов выполнялись не...

Выполнение всех логических операторов в блоках
Имеется: foreach (ISomeItem item in tableItems) { var deletedItem =...

9
hoggy
Эксперт С++
7625 / 3432 / 713
Регистрация: 15.11.2014
Сообщений: 7,840
Завершенные тесты: 1
04.10.2017, 22:44 2
Цитата Сообщение от Valeryn Посмотреть сообщение
_Tp
UB.
0
Valeryn
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 264
04.10.2017, 22:51  [ТС] 3
Цитата Сообщение от hoggy Посмотреть сообщение
UB.
what?
0
hoggy
Эксперт С++
7625 / 3432 / 713
Регистрация: 15.11.2014
Сообщений: 7,840
Завершенные тесты: 1
04.10.2017, 23:49 4
Цитата Сообщение от Valeryn Посмотреть сообщение
what?
Функция принимает любое количество строк а затем складывает их
1
04.10.2017, 23:49
Valeryn
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 264
04.10.2017, 23:59  [ТС] 5
Цитата Сообщение от hoggy Посмотреть сообщение
Функция принимает любое количество строк а затем складывает их
ну окей, нажму ctrl+f

А по делу как дела обстоят?
0
DU3
281 / 233 / 114
Регистрация: 07.09.2016
Сообщений: 587
05.10.2017, 02:49 6
Лучший ответ Сообщение было отмечено Valeryn как решение

Решение

можно но очень сложно. если я правильно понял суть, то это дело похоже на то, что мейерс в своей первой книге 35 советов или бла бла бла упоминает как отложенные вычисления и прокси классы. возможно у кого-то другого это описано, я не помню. суть примерно в следующем:
допустим есть две матрицы IntMatrix:
в обычной реализации сигнатура оператора + такова, что возвращается тоже IntMatrix.
В случае отложенного вычисления возвращаемый объект - некая прокси хрень, которая внутри себя помнит,
что она породилась результатом сложения двух матриц. Когда реально потребуется результат - происходит неявный
каст в IntMatrix и внутри этого каста уже происходит собственно сложение. Чтобы это все незаметно работало для
пользователей матриц, нужно уметь строить такие вот проксихрени, определять для них тоже весь набор операций
как с матрицами, так и с такими же хренями, которые опять же порождают подобные проксихрени.
есть еще вариант, когда проксихрени - не публичные типы, а приватные, с которыми умеют работать только матрицы.
но это не сильно упрощает дело. + возникает момент неопределенности собственно вычислений а значит сложности
с исключениями в неожиданных местах. в общем это не тривиальная вещь и с нуля ее писать не стоит. если критична
производительность, то лучше подискать спец библиотеки с матричными вычислениями. в них так же могут присутствовать
и всякие процессорнозависимые вычисления и может быть даже параллельные и всякие другие хитрости. в общем дело
это сложное.

на TBB посмотрите если производительность критична.
0
DrOffset
11385 / 6138 / 1495
Регистрация: 30.01.2014
Сообщений: 10,001
05.10.2017, 08:23 7
Цитата Сообщение от DU3 Посмотреть сообщение
возможно у кого-то другого это описано, я не помню
Написано про это в книге "Шаблоны С++. Справочник разрабочика".
0
GbaLog-
Любитель чаепитий
3208 / 1511 / 472
Регистрация: 24.08.2014
Сообщений: 5,288
Записей в блоге: 1
Завершенные тесты: 2
05.10.2017, 08:45 8
del
0
Mirmik
techpriest
631 / 210 / 57
Регистрация: 27.02.2014
Сообщений: 1,162
05.10.2017, 09:10 9
Решение про единый цикл не очень отвечает концепции матричной арифметики.
Скалярное умножение элементов матрицы не является интуитивно понятной интерпретацией оператора умножения относительно матриц.

Я бы предложил концепцию vectorized функций. То есть сделать механизм, который бы применял

C++
1
Matrix invoke_vectorized(Function function, MatrixArguments ... matrixs);
,

где function:
C++
1
2
3
[](double a, double b, double c, double d) {
return a + b * c / d;
}
лямбда операции над скалярами.

Это будет академичненько.
Прокси арифметика - это круто, но случай, ИМХО, не тот...
0
Valeryn
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 264
05.10.2017, 09:19  [ТС] 10
Все, понял как это можно реализовать.
Но профита нет.

Ради демлнстрационных примеров, тащить ublas буста весь как то не охото.

Добавлено через 4 минуты
Скалярное умножение у меня реализовано оператором ^
Я про простые операции, типо умножение ° (не помню слово) сложение, разница и т.д.
0
05.10.2017, 09:19
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.10.2017, 09:19

Оптимизация кода и выполнение табуляции
Всем доброго времени суток. Есть задача6 Для чисел от 1 до 10 вычислить квадрат, куб и 4-й...

ActiveRecord. Выполнение insert в foreach. Оптимизация
Вообщем ситуация такая. Есть запрос insert который выполняется в цикле foreach по средством...

. Отметьте, выполнение каких операторов приведет к выходу за приделы заданного массива
DIM a ( -5 TO 10) AS INTEGER а) FOR i = 1 TO 15: a ( i - 6 ) = i : NEXT б) FOR i = -1 TO 16:...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.