|
|
|
Избыточное копирование объекта при реализации оператора умножения и оператора присваивания21.03.2016, 18:43. Показов 6128. Ответов 84
Метки нет (Все метки)
Есть класс работы с матрицами. Есть операция умножения матриц, описанная как оператор класса. В данном коротком примере я просто моделирую ситуацию. Реальное наполнение класса принципиальной разницы не играет, нужно просто понимать, что оператор умножения будет иметь большой код, оператор присваивания в реализации тоже будет не пустым. Эти места в примере засвечены комментариями
C++ #include <cstdio> class Matrix { private: // внутренние данные матрицы public: Matrix (); Matrix (const Matrix&); ~Matrix (); Matrix& operator=(const Matrix& a); Matrix operator*(const Matrix& a) const; }; Matrix::Matrix () { printf ("Matrix ()\n"); }; Matrix::Matrix (const Matrix&) { printf ("Matrix (const Matrix&)\n"); }; Matrix::~Matrix () { printf ("~Matrix ()\n"); }; Matrix& Matrix::operator=(const Matrix& a) { printf ("operator=(const Matrix&)\n"); // тут как бы код, копирущий данные из "a" в "this" return *this; } Matrix Matrix::operator*(const Matrix& a) const { printf ("operator*(const Matrix&)\n"); Matrix result; // тут как бы код, умножающий "a" и "this" и записывающий // данные в "result" return result; } Matrix a, b, c; int main (void) { printf ("------------------\n"); a = b * c; printf ("------------------\n"); } Code $ g++-4.8 t.cc $ ./a.out Matrix () Matrix () Matrix () ------------------ operator*(const Matrix&) Matrix () operator=(const Matrix&) ~Matrix () ------------------ ~Matrix () ~Matrix () ~Matrix () Посмотрим на ассемблерный код. Компилирую с опцией -fno-inline, чтобы оставаться с короткой программой и не разводить геморрой по борьбе с inline'ом со стороны компилятора. В общем случае тела операторов класса Matrix будут в отдельном файле и НЕ будут доступны для inline'а. Опцию -fno-exceptions подаю, чтобы было меньше мусора в коде Code $ g++ t.cc -O2 -fno-inline -fno-exceptions $ cat t.s ... leal -9(%ebp), %ebx subl $32, %esp movl %ebx, (%esp) movl $c, 8(%esp) movl $b, 4(%esp) call _ZN6MatrixmlERKS_ <- operator* subl $4, %esp movl %ebx, 4(%esp) movl $a, (%esp) call _ZN6MatrixaSERKS_ <- operator= ... C typedef struct { /* внутренности */ } Matrix; extern void operator_assign (Matrix *this, const Matrix *value); extern void operator_mul (Matrix *result, const Matrix *this, const Matrix *operand2); Matrix a, b, c; int main (void) { Matrix tmp; operator_mul (&tmp, &b, &c); /* tmp = b.operator* (c) */ operator_assign (&a, &tmp); /* a.operator= (tmp) */ } C operator_mul (&a, &b, &c); Вопрос. Как правильно написать текст на C++, чтобы получить код, эквивалентный вышеприведённой эффективной реализации на C? Оставаясь при этом в объёме стандарта C++98. Оставляя исходник в понятном и читабельном виде, без использования извращений типа семиэтажных шаблонов и т.п.
0
|
|
| 21.03.2016, 18:43 | |
|
Ответы с готовыми решениями:
84
Неправильная работа оператора присваивания после работы оператора суммирования От каких ошибок страхует Const при перегрузке оператора присваивания
|
|
|
||
| 23.03.2016, 15:08 [ТС] | ||
|
Кликните здесь для просмотра всего текста
C++ struct Matrix4 { private: float mat[16]; public: Matrix4(); float operator[](int ind) const { return mat[ind]; } float& operator[](int ind) { return mat[ind]; } static void operator_mul(Matrix4& ret, const Matrix4& mat, const Matrix4& m); }; void Matrix4::operator_mul(Matrix4& ret, const Matrix4& mat, const Matrix4& m) { ret[0] = mat[0] * m[0] + mat[4] * m[1] + mat[8] * m[2] + mat[12] * m[3]; ret[1] = mat[1] * m[0] + mat[5] * m[1] + mat[9] * m[2] + mat[13] * m[3]; ret[2] = mat[2] * m[0] + mat[6] * m[1] + mat[10] * m[2] + mat[14] * m[3]; ret[3] = mat[3] * m[0] + mat[7] * m[1] + mat[11] * m[2] + mat[15] * m[3]; ret[4] = mat[0] * m[4] + mat[4] * m[5] + mat[8] * m[6] + mat[12] * m[7]; ret[5] = mat[1] * m[4] + mat[5] * m[5] + mat[9] * m[6] + mat[13] * m[7]; ret[6] = mat[2] * m[4] + mat[6] * m[5] + mat[10] * m[6] + mat[14] * m[7]; ret[7] = mat[3] * m[4] + mat[7] * m[5] + mat[11] * m[6] + mat[15] * m[7]; ret[8] = mat[0] * m[8] + mat[4] * m[9] + mat[8] * m[10] + mat[12] * m[11]; ret[9] = mat[1] * m[8] + mat[5] * m[9] + mat[9] * m[10] + mat[13] * m[11]; ret[10] = mat[2] * m[8] + mat[6] * m[9] + mat[10] * m[10] + mat[14] * m[11]; ret[11] = mat[3] * m[8] + mat[7] * m[9] + mat[11] * m[10] + mat[15] * m[11]; ret[12] = mat[0] * m[12] + mat[4] * m[13] + mat[8] * m[14] + mat[12] * m[15]; ret[13] = mat[1] * m[12] + mat[5] * m[13] + mat[9] * m[14] + mat[13] * m[15]; ret[14] = mat[2] * m[12] + mat[6] * m[13] + mat[10] * m[14] + mat[14] * m[15]; ret[15] = mat[3] * m[12] + mat[7] * m[13] + mat[11] * m[14] + mat[15] * m[15]; } Скомпилируем его "не думая": Code $ g++ t.cc -O3 -S $ cat t.s Кликните здесь для просмотра всего текста
Code _ZN7Matrix412operator_mulERS_RKS_S2_: .LFB2: .cfi_startproc movss (%rsi), %xmm0 movss (%rdx), %xmm1 mulss %xmm0, %xmm1 movss 16(%rsi), %xmm0 mulss 4(%rdx), %xmm0 addss %xmm1, %xmm0 movss 32(%rsi), %xmm1 mulss 8(%rdx), %xmm1 addss %xmm1, %xmm0 movss 48(%rsi), %xmm1 mulss 12(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, (%rdi) movss 4(%rsi), %xmm0 movss (%rdx), %xmm1 mulss %xmm0, %xmm1 movss 20(%rsi), %xmm0 mulss 4(%rdx), %xmm0 addss %xmm1, %xmm0 movss 36(%rsi), %xmm1 mulss 8(%rdx), %xmm1 addss %xmm1, %xmm0 movss 52(%rsi), %xmm1 mulss 12(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 4(%rdi) movss 8(%rsi), %xmm0 movss (%rdx), %xmm1 mulss %xmm0, %xmm1 movss 24(%rsi), %xmm0 mulss 4(%rdx), %xmm0 addss %xmm1, %xmm0 movss 40(%rsi), %xmm1 mulss 8(%rdx), %xmm1 addss %xmm1, %xmm0 movss 56(%rsi), %xmm1 mulss 12(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 8(%rdi) movss 12(%rsi), %xmm0 movss (%rdx), %xmm1 mulss %xmm0, %xmm1 movss 28(%rsi), %xmm0 mulss 4(%rdx), %xmm0 addss %xmm1, %xmm0 movss 44(%rsi), %xmm1 mulss 8(%rdx), %xmm1 addss %xmm1, %xmm0 movss 60(%rsi), %xmm1 mulss 12(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 12(%rdi) movss (%rsi), %xmm0 movss 16(%rdx), %xmm1 mulss %xmm0, %xmm1 movss 16(%rsi), %xmm0 mulss 20(%rdx), %xmm0 addss %xmm1, %xmm0 movss 32(%rsi), %xmm1 mulss 24(%rdx), %xmm1 addss %xmm1, %xmm0 movss 48(%rsi), %xmm1 mulss 28(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 16(%rdi) movss 4(%rsi), %xmm0 movss 16(%rdx), %xmm1 mulss %xmm0, %xmm1 movss 20(%rsi), %xmm0 mulss 20(%rdx), %xmm0 addss %xmm1, %xmm0 movss 36(%rsi), %xmm1 mulss 24(%rdx), %xmm1 addss %xmm1, %xmm0 movss 52(%rsi), %xmm1 mulss 28(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 20(%rdi) movss 8(%rsi), %xmm0 movss 16(%rdx), %xmm1 mulss %xmm0, %xmm1 movss 24(%rsi), %xmm0 mulss 20(%rdx), %xmm0 addss %xmm1, %xmm0 movss 40(%rsi), %xmm1 mulss 24(%rdx), %xmm1 addss %xmm1, %xmm0 movss 56(%rsi), %xmm1 mulss 28(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 24(%rdi) movss 12(%rsi), %xmm0 movss 16(%rdx), %xmm1 mulss %xmm0, %xmm1 movss 28(%rsi), %xmm0 mulss 20(%rdx), %xmm0 addss %xmm1, %xmm0 movss 44(%rsi), %xmm1 mulss 24(%rdx), %xmm1 addss %xmm1, %xmm0 movss 60(%rsi), %xmm1 mulss 28(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 28(%rdi) movss (%rsi), %xmm0 movss 32(%rdx), %xmm1 mulss %xmm0, %xmm1 movss 16(%rsi), %xmm0 mulss 36(%rdx), %xmm0 addss %xmm1, %xmm0 movss 32(%rsi), %xmm1 mulss 40(%rdx), %xmm1 addss %xmm1, %xmm0 movss 48(%rsi), %xmm1 mulss 44(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 32(%rdi) movss 4(%rsi), %xmm0 movss 32(%rdx), %xmm1 mulss %xmm0, %xmm1 movss 20(%rsi), %xmm0 mulss 36(%rdx), %xmm0 addss %xmm1, %xmm0 movss 36(%rsi), %xmm1 mulss 40(%rdx), %xmm1 addss %xmm1, %xmm0 movss 52(%rsi), %xmm1 mulss 44(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 36(%rdi) movss 8(%rsi), %xmm0 movss 32(%rdx), %xmm1 mulss %xmm0, %xmm1 movss 24(%rsi), %xmm0 mulss 36(%rdx), %xmm0 addss %xmm1, %xmm0 movss 40(%rsi), %xmm1 mulss 40(%rdx), %xmm1 addss %xmm1, %xmm0 movss 56(%rsi), %xmm1 mulss 44(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 40(%rdi) movss 12(%rsi), %xmm0 mulss 32(%rdx), %xmm0 movaps %xmm0, %xmm1 movss 28(%rsi), %xmm0 mulss 36(%rdx), %xmm0 addss %xmm1, %xmm0 movss 44(%rsi), %xmm1 mulss 40(%rdx), %xmm1 addss %xmm1, %xmm0 movss 60(%rsi), %xmm1 mulss 44(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 44(%rdi) movss (%rsi), %xmm0 movss 48(%rdx), %xmm1 mulss %xmm0, %xmm1 movss 16(%rsi), %xmm0 mulss 52(%rdx), %xmm0 addss %xmm1, %xmm0 movss 32(%rsi), %xmm1 mulss 56(%rdx), %xmm1 addss %xmm1, %xmm0 movss 48(%rsi), %xmm1 mulss 60(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 48(%rdi) movss 4(%rsi), %xmm0 mulss 48(%rdx), %xmm0 movaps %xmm0, %xmm1 movss 20(%rsi), %xmm0 mulss 52(%rdx), %xmm0 addss %xmm1, %xmm0 movss 36(%rsi), %xmm1 mulss 56(%rdx), %xmm1 addss %xmm1, %xmm0 movss 52(%rsi), %xmm1 mulss 60(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 52(%rdi) movss 8(%rsi), %xmm0 movss 48(%rdx), %xmm1 mulss %xmm0, %xmm1 movss 24(%rsi), %xmm0 mulss 52(%rdx), %xmm0 addss %xmm1, %xmm0 movss 40(%rsi), %xmm1 mulss 56(%rdx), %xmm1 addss %xmm1, %xmm0 movss 56(%rsi), %xmm1 mulss 60(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 56(%rdi) movss 12(%rsi), %xmm0 mulss 48(%rdx), %xmm0 movaps %xmm0, %xmm1 movss 28(%rsi), %xmm0 mulss 52(%rdx), %xmm0 addss %xmm1, %xmm0 movss 44(%rsi), %xmm1 mulss 56(%rdx), %xmm1 addss %xmm1, %xmm0 movss 60(%rsi), %xmm1 mulss 60(%rdx), %xmm1 addss %xmm1, %xmm0 movss %xmm0, 60(%rdi) ret .cfi_endproc .LFE2: .size _ZN7Matrix412operator_mulERS_RKS_S2_, .-_ZN7Matrix412operator_mulERS_RKS_S2_ Скомпилируем его "по умному" (под конкретную архитектуру): Code $ g++ t.cc -O3 -march=haswell -S $ cat t.s Кликните здесь для просмотра всего текста
Code _ZN7Matrix412operator_mulERS_RKS_S2_: .LFB2: .cfi_startproc vmovss (%rsi), %xmm1 vmovss 32(%rsi), %xmm2 vmovss 48(%rsi), %xmm3 vmovss 16(%rsi), %xmm0 vmulss 4(%rdx), %xmm0, %xmm0 vfmadd231ss (%rdx), %xmm1, %xmm0 vfmadd231ss 8(%rdx), %xmm2, %xmm0 vfmadd231ss 12(%rdx), %xmm3, %xmm0 vmovss %xmm0, (%rdi) vmovss 4(%rsi), %xmm4 vmovss 52(%rsi), %xmm6 vmovss 20(%rsi), %xmm0 vmovss 36(%rsi), %xmm5 vmulss 4(%rdx), %xmm0, %xmm0 vfmadd231ss (%rdx), %xmm4, %xmm0 vfmadd231ss 8(%rdx), %xmm5, %xmm0 vfmadd231ss 12(%rdx), %xmm6, %xmm0 vmovss %xmm0, 4(%rdi) vmovss 8(%rsi), %xmm7 vmovss 40(%rsi), %xmm1 vmovss 56(%rsi), %xmm2 vmovss 24(%rsi), %xmm0 vmulss 4(%rdx), %xmm0, %xmm0 vfmadd231ss (%rdx), %xmm7, %xmm0 vfmadd231ss 8(%rdx), %xmm1, %xmm0 vfmadd231ss 12(%rdx), %xmm2, %xmm0 vmovss %xmm0, 8(%rdi) vmovss 12(%rsi), %xmm3 vmovss 44(%rsi), %xmm4 vmovss 28(%rsi), %xmm0 vmulss 4(%rdx), %xmm0, %xmm0 vfmadd231ss (%rdx), %xmm3, %xmm0 vfmadd231ss 8(%rdx), %xmm4, %xmm0 vmovss 60(%rsi), %xmm5 vfmadd231ss 12(%rdx), %xmm5, %xmm0 vmovss %xmm0, 12(%rdi) vmovss (%rsi), %xmm6 vmovss 32(%rsi), %xmm7 vmovss 48(%rsi), %xmm1 vmovss 16(%rsi), %xmm0 vmulss 20(%rdx), %xmm0, %xmm0 vfmadd231ss 16(%rdx), %xmm6, %xmm0 vfmadd231ss 24(%rdx), %xmm7, %xmm0 vfmadd231ss 28(%rdx), %xmm1, %xmm0 vmovss %xmm0, 16(%rdi) vmovss 4(%rsi), %xmm2 vmovss 36(%rsi), %xmm3 vmovss 52(%rsi), %xmm4 vmovss 20(%rsi), %xmm0 vmulss 20(%rdx), %xmm0, %xmm0 vfmadd231ss 16(%rdx), %xmm2, %xmm0 vfmadd231ss 24(%rdx), %xmm3, %xmm0 vfmadd231ss 28(%rdx), %xmm4, %xmm0 vmovss %xmm0, 20(%rdi) vmovss 8(%rsi), %xmm5 vmovss 40(%rsi), %xmm6 vmovss 56(%rsi), %xmm7 vmovss 24(%rsi), %xmm0 vmulss 20(%rdx), %xmm0, %xmm0 vfmadd231ss 16(%rdx), %xmm5, %xmm0 vfmadd231ss 24(%rdx), %xmm6, %xmm0 vfmadd231ss 28(%rdx), %xmm7, %xmm0 vmovss %xmm0, 24(%rdi) vmovss 28(%rsi), %xmm0 vmovss 12(%rsi), %xmm1 vmulss 20(%rdx), %xmm0, %xmm0 vfmadd231ss 16(%rdx), %xmm1, %xmm0 vmovss 44(%rsi), %xmm2 vfmadd231ss 24(%rdx), %xmm2, %xmm0 vmovss 60(%rsi), %xmm3 vfmadd231ss 28(%rdx), %xmm3, %xmm0 vmovss %xmm0, 28(%rdi) vmovss (%rsi), %xmm4 vmovss 32(%rsi), %xmm5 vmovss 48(%rsi), %xmm6 vmovss 16(%rsi), %xmm0 vmulss 36(%rdx), %xmm0, %xmm0 vfmadd231ss 32(%rdx), %xmm4, %xmm0 vfmadd231ss 40(%rdx), %xmm5, %xmm0 vfmadd231ss 44(%rdx), %xmm6, %xmm0 vmovss %xmm0, 32(%rdi) vmovss 4(%rsi), %xmm7 vmovss 36(%rsi), %xmm1 vmovss 52(%rsi), %xmm2 vmovss 20(%rsi), %xmm0 vmulss 36(%rdx), %xmm0, %xmm0 vfmadd231ss 32(%rdx), %xmm7, %xmm0 vfmadd231ss 40(%rdx), %xmm1, %xmm0 vfmadd231ss 44(%rdx), %xmm2, %xmm0 vmovss %xmm0, 36(%rdi) vmovss 8(%rsi), %xmm3 vmovss 40(%rsi), %xmm4 vmovss 56(%rsi), %xmm5 vmovss 24(%rsi), %xmm0 vmulss 36(%rdx), %xmm0, %xmm0 vfmadd231ss 32(%rdx), %xmm3, %xmm0 vfmadd231ss 40(%rdx), %xmm4, %xmm0 vfmadd231ss 44(%rdx), %xmm5, %xmm0 vmovss %xmm0, 40(%rdi) vmovss 28(%rsi), %xmm0 vmovss 12(%rsi), %xmm6 vmovss 44(%rsi), %xmm7 vmovss 60(%rsi), %xmm1 vmulss 36(%rdx), %xmm0, %xmm0 vfmadd231ss 32(%rdx), %xmm6, %xmm0 vfmadd231ss 40(%rdx), %xmm7, %xmm0 vfmadd231ss 44(%rdx), %xmm1, %xmm0 vmovss %xmm0, 44(%rdi) vmovss (%rsi), %xmm2 vmovss 48(%rsi), %xmm4 vmovss 16(%rsi), %xmm0 vmovss 32(%rsi), %xmm3 vmulss 52(%rdx), %xmm0, %xmm0 vfmadd231ss 48(%rdx), %xmm2, %xmm0 vfmadd231ss 56(%rdx), %xmm3, %xmm0 vfmadd231ss 60(%rdx), %xmm4, %xmm0 vmovss %xmm0, 48(%rdi) vmovss 4(%rsi), %xmm5 vmovss 36(%rsi), %xmm6 vmovss 20(%rsi), %xmm0 vmovss 52(%rsi), %xmm7 vmulss 52(%rdx), %xmm0, %xmm0 vfmadd231ss 48(%rdx), %xmm5, %xmm0 vfmadd231ss 56(%rdx), %xmm6, %xmm0 vfmadd231ss 60(%rdx), %xmm7, %xmm0 vmovss %xmm0, 52(%rdi) vmovss 24(%rsi), %xmm0 vmovss 8(%rsi), %xmm1 vmulss 52(%rdx), %xmm0, %xmm0 vfmadd231ss 48(%rdx), %xmm1, %xmm0 vmovss 40(%rsi), %xmm2 vfmadd231ss 56(%rdx), %xmm2, %xmm0 vmovss 56(%rsi), %xmm3 vfmadd231ss 60(%rdx), %xmm3, %xmm0 vmovss %xmm0, 56(%rdi) vmovss 28(%rsi), %xmm0 vmovss 12(%rsi), %xmm4 vmulss 52(%rdx), %xmm0, %xmm0 vfmadd231ss 48(%rdx), %xmm4, %xmm0 vmovss 44(%rsi), %xmm5 vfmadd231ss 56(%rdx), %xmm5, %xmm0 vmovss 60(%rsi), %xmm6 vfmadd231ss 60(%rdx), %xmm6, %xmm0 vmovss %xmm0, 60(%rdi) ret .cfi_endproc .LFE2: .size _ZN7Matrix412operator_mulERS_RKS_S2_, .-_ZN7Matrix412operator_mulERS_RKS_S2_ Я не разбираюсь в intel'овской архитектуре и мне совершенно впадлу разбираться с опциями компилятора, чтобы получить максимально быстро работающий код конкретно под мою модель процессора. Но если библиотека работы с матрицами предоставлена мне в виде файла *.h, внутри которого написано тело (для инлайна со стороны компилятора), то я, как простой пользователь, скорее всего не смогу получить предельной производительности. Потому что для работы с этим файлом *.h мне придётся прочитать кучу мануалов, чтобы понять, с какими же опциями мне надо собирать. Да и неизвестно ещё, может получиться так, что эти опции ускорят код умножения матрицы, но замедлят что-нибудь другое. А вот если мне уже выдана библиотека в виде бинарника, над которой уже поработали профессионалы, то я с очень большой вероятностью получу более быстрый код, чем когда буду корячиться самостоятельно с файлом *.h. К тому же вариант с файлом *.h очень сильно зависит от компилятора: один умеет эффективно инлайнить, другой не умеет, в одном уже появилась поддержка топовых версий процессора, в другом ещё не появилась. Т.е. оптимизации в жизни бывают разных уровней. Инлайн - это машинно-НЕзависимая оптимизация, использование всяких векторных аппаратных инструкций - уже машинно-зависимая. И при написании эффективного кода нужно учитывать в том числе и такие вещи
0
|
||
|
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
|
|
| 23.03.2016, 15:29 | |
|
0
|
|
|
|
||
| 23.03.2016, 15:32 [ТС] | ||
|
0
|
||
|
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
|
||
| 23.03.2016, 15:37 | ||
|
Если библиотека поставляется в бинарном виде - то наружу торчат extern "C" + хедер с инлайн обертками. Просто эти обертки - более высокая абстракция и оптимизации там могут быть платформо-независимыми с шаблонной магией. А весь низкоуровневый код упрятан внутрь.
0
|
||
|
|
|
| 23.03.2016, 15:42 [ТС] | |
|
Это понятно. Я просто рассказывал Nosey'у про оптимизации (а точнее, их разные виды). Если inline должен выполнять любой более-менее приличный компилятор C++ (без этого с C++ никак), то с платформо-зависимыми оптимизациями всё намного сложнее. И упрятав такой оптимизированный код в бинарник, поставщик библиотеки в общем случае для пользователя гарантирует более эффективный код, чем в варианте, когда пользователю выдаётся хидер в чистом стиле Си++ (т.е. со всеми потрохами), а пользователь сам не сумеет применить к нему платформо-зависимые оптимизации
0
|
|
|
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
|
|
| 23.03.2016, 15:49 | |
|
Evg, Есть 2 но:
1) Интел поймали за ж..у с их "платформо-зависимыми оптимизациями". 2) Если пользователь использует "плохой" компилятор, то и на оптимальность реализации ему покласть.
0
|
|
|
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
|
|||||
| 23.03.2016, 16:05 | |||||
![]() a = b+c, враппер после простого инлайна(который сможет любой компилятор) превратит в С подход opAdd(a,b,c); но этот код уже не будет инициализацией, а будет "присваиванием" переменной а, следовательно не каждый компилятор сможет это оптимизировать также хорошо, как Mat a = b + c;. Но в случае с С подходом с уже выделенной памятью, это не проблема конечно.Незабываем что разговор о статической линковке. В динамике используем С подход и ни как иначе. Также если вы пишите воистину что-то требующее такой производительности, то незнание целевой архитектуры будет меньшая из ваших бед, ибо это просто недельное чтение мануалов. И вам придется их прочитать. Если же это не клиентский софт а бэкенд, то тут точно придется прочитать мануалы, ибо писать под определенное железо и лень в прочтении мануалов по 10 флагам - плохо сочетаются ) Но самое важное в нашей дискуссии, это соотношение затрат на работу с интерфейсом к затратам на саму внутреннюю работу библиотеки. Например, openGl, помните изменения его интерфейса от версии к версии? Правильно, ранее в Gl1 когда мы не могли себе позволить разрешение 800*600, мы рисовали по точкам, а сейчас в Gl4 мы просим oGL отрисовать нам VAO включающий в себя гору данных для отрисовки. Интерфейс скрывает за собой все больше и больше, так почему вы желаете вынести перемножение матриц в библиотеку? Это опять же риторический вопрос.
0
|
|||||
|
|
||||
| 23.03.2016, 16:09 [ТС] | ||||
|
Есть ещё один момент. Когда код описан в файле *.h, то, например, при работе под отладчиком код нужно собирать в режиме -O0 -g, а такой код будет на порядок (а и то и больше) медленнее работать за счёт того, что инлайн уже работать не будет, и эффект от его отсутствия будет выглядеть как большое количество мусорного кода, которое есть побочный выхлоп C++, который базируется на инлайне со стороны компилятора. В итоге, если в боевой версии программы происходит падение через минуту после старты программы, то в отладочной версии падение может быть и через 10 минут, и через час. При этом пользователю режим -O0 -g нужен в общем-то только для своих собственных кодов, а не библиотечных, но т.к. библиотечные коды представлены в виде потрохов, то начинают медленно работать ещё и они (да ещё и занимают основную часть времени работы) Добавлено через 1 минуту
0
|
||||
|
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
|
|
| 23.03.2016, 16:18 | |
|
0
|
|
|
|
|||||||
| 23.03.2016, 16:21 [ТС] | |||||||
![]() Добавлено через 1 минуту
0
|
|||||||
|
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
|
||
| 23.03.2016, 16:37 | ||
|
Добавлено через 56 секунд Дипетчер в рантайме.
0
|
||
|
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
|
||
| 23.03.2016, 16:43 | ||
|
0
|
||
|
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
|
||||||
| 23.03.2016, 19:22 | ||||||
|
Собственно справляться можно с длительностью работы : корректировкой входных данных и тестами. С длительностью работы определённого кода - билд системой, никто вас не заставляет библиотеку тоже собирать в дебаг режиме если вам ее дебажить не надо. 1) Есть ли у студии и шланга технология подобная "--enable-gnu-indirect-function" из коробки? 2) У меня ни один gcc не сконфигурирован с этим флагом, что подталкивает на мысль, а работает ли вообще эта технология в gcc, или это модная приблуда работающая только при свете луны? ![]() Но идею, что вам таки придется почитать мануалы это не отменяет ни в какой ситуации, ну разве что ваш код это "Hello World" на основе адской библиотеки, или же вы нашли библиотеку которая умеет "делать мне хорошо"? Если библиотека доставляется к клиенту не вами, то см. динамическую линковку выше. Если вами и статическая линковка, то возвращаемся к прошлым сообщениям, но я уже устал об этом говорить, я не сомневаюсь что вы меня поняли ![]() 1) Если рассматривать шарообразное произведение матриц в вакууме, то перечитать все с первого поста. 2) Если перемножение миллиона раз примерочных матриц занимает 1нс, то есть три варианта: 1) инлайниг. 2) В случае выноса в библиотеку без возможности инлайнинга - оторвать ноги архитектору, при повторении - оторвать руки. 3) С подход, как самый нежелательный в контексте использования, да, лучше оторвать ноги , но всеядный способ.3) Если одно перемножение матриц занимает миллион секунд, то есть один вариант: 1) предлагаю в интерфейс перемножения в параметр обязательно передавать по значению всю санту барбару в raw качестве, на скорость это не повлияет, а разработчики улыбнутся, да и будет что посмотреть во время рассчетов. 4) В средних ситуациях одна фигня - что инлайн, что С подход, ибо общее время рассчетов будет такое, что я даже вспомнить название "санта барбара" не успею.
0
|
||||||
|
|
||||||||
| 23.03.2016, 20:07 [ТС] | ||||||||
|
0
|
||||||||
|
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
|
|||||||
| 23.03.2016, 21:25 | |||||||
|
А обычные матрицы, хорошо, да. Но если вы желаете паралелить на GPU умножение матриц через интерфейс a = b*c. То я предлагаю пари, что я на SIMD инструкциях это сделаю быстрее, чем вы будете ожидать синхронизации GPU и CPU. Или же мы уже где-то незаметно перешли от еденичного интерфейса к пакетному? Или же я просто не понял вопроса?А если отвечать "по-теме", то интерфейс opengl рассчитан на то чтобы никакого lto в помине не надо было, ибо это капля в море. А мной приводимый код показывал на умножении матриц 30%'ый буст между С подходом и С++ подходом, если для вас 30% это недостаточно, чтобы отказаться от одной технологии в пользу другой, или хотя бы рассмотреть её, принимая во внимание что это синтетический тест в тепличных условиях, то я могу лишь посочувствовать.
0
|
|||||||
|
|
|||||
| 23.03.2016, 22:02 [ТС] | |||||
|
Твой замер выглядел как (чтобы было перед глазами): 99999999 196025-fill 99999999 1958025-cpp 99999999 2202373-cpp no-inline + 1 copy ctor 99999999 2784633-c Мой замер в режиме -O3: 99999999 248-fill 99999999 4150-cpp 99999999 4259-cpp no-inline + 1 copy ctor 99999999 2870-c Мой замер в режиме -O3 -flto: 99999999 218-fill 99999999 1732-cpp 99999999 2090-cpp no-inline + 1 copy ctor 99999999 3120-c Из этих цифр я могу сделать только один вывод - что делает режим -flto, непонятно, как он ухитряется пессимизировать код, тоже непонятно, как в таких условиях вообще можно что-то сравнивать - тоже не понятно. В режиме без -flto (что эквивалентно модели, в которой я изначально работаю в этой теме) код в стиле Си++ ожидаемо более медленный
0
|
|||||
|
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
|
||||||||||||||||
| 23.03.2016, 22:47 | ||||||||||||||||
![]() ) как же ускорение компиляции путем переноса кода в другую единицу трансляции? ведь LTO включаем только для релиза, а в дебаге без LTO, при этом пишем код как обычно, не задумываясь об инлайне, а потом добрый компилятор нам поможет. Глупо отказывать от помощи, если есть такая возможность, не правда ли?Но в случае библиотек, мы уже все обсудили и я согласен ![]() Но я могу привести простое доказательство что эти измерения верны, и объяснение(точнее подтверждение слов DrOffset'a на первой странице в 8-ом сообщении) :При изменении моего кода с
В завершение цитата сегодняшнего дня:
0
|
||||||||||||||||
|
|
||||||
| 24.03.2016, 09:38 [ТС] | ||||||
|
Добавлено через 3 минуты
0
|
||||||
|
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
|
||||||||
| 24.03.2016, 11:51 | ||||||||
![]() У меня таких результатов не было, у меня результаты с разными погрешностями вот такие: < означает быстрее, то что слева - быстрее. без lto : (C-подход) < (CPP inline) < (CPP noInline) - тут везде минимальный отрыв с максимумом в 5%. с lto : (CPP inline) < (CPP noInline) < (C-подход) - тут ровно то что я указывал ранее, C-подход отстает очень знатно. Но таких адских результатов как у тебя я не видел. Откуда вопросы есть: Точно ли адекватно проводился тест (cpu был свободен)? Что за версия gcc? Что за cpu? Как насчет -march=native для всех тестов? У меня lto версия ускоряет весь код на 40%, как С, так и С++.
0
|
||||||||
| 24.03.2016, 11:51 | |
|
Какое значение получит переменная p при выполнении следующего оператора присваивания? Ошибка при выполнении оператора присваивания производного класса через указатель на базовый Ошибка при реализации перегрузки оператора <<
Переопределение оператора присваивания Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации:
1. Вернуть возможность использования знаков | 1 l I;. . .
|
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С.
Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
|
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию?
Фраза «Любая достаточно развитая технология неотличима от магии». . .
|
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль?
Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
|
|
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология.
«Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
|
Генератор паролей (вариант №2)
Maks 30.10.2026
Обновленная версия ранее созданной обработки.
Добавлены следующие реквизиты типа Булево:
- Буквы;
- Цифры;
- Символы.
Изменена логика команды "Сгенерировать" и процедуры "ПриОткрытии":. . .
|
Генератор паролей (вариант №1)
Maks 29.10.2026
Реализация из решения ниже выполнена исключительно по моей инициативе, дабы облегчить себе работу в создании паролей для администрируемых мною сервисов и пользователей.
Самым главным критерием для. . .
|
Установка ChatGPT (Codex) на Windows без использования Microsoft Store
Fabien159 28.10.2026
Здравствуйте всем читающим! Опишу процесс установки ChatGPT (Codex) на Windows, если по каким-то причинам у вас не получается устанавить его через Microsoft Store.
И так:
1. Скачиваем с. . .
|