|
|
|
Избыточное копирование объекта при реализации оператора умножения и оператора присваивания21.03.2016, 18:43. Показов 5615. Ответов 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 при выполнении следующего оператора присваивания? Ошибка при выполнении оператора присваивания производного класса через указатель на базовый Ошибка при реализации перегрузки оператора <<
Переопределение оператора присваивания Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал.
Оно само - говорит.
Кто слышит тот слышит.
|
Оказывается, Unreal Engine позволяет качество на порядки выше, чем было в Lineedge
Etyuhibosecyu 05.07.2026
Жаль, конечно, что я не узнал об этом, пока Lineedge существовала, а то бы Noname2331 написал, что волки превращаются в пиксельную кашу, а я бы его попросил скачать какую-нибудь бриллиантовую или Pro. . .
|
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было
ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась.
Первый вариант. . .
|
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2.
Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
|
|
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет.
Но обычно это 50 лет и более.
Наверное, закисление почвы происходит сезонно в средней. . .
|
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
|
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS
Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
|
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи.
Через несколько переработок от PHP кода к C89 (надеюсь, 89).
Но довольно запутанно получилось. Код для Linux.
Но если убрать time и то, что с ним. . .
|