Форум программистов, компьютерный форум CyberForum.ru

const float & - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 28, средняя оценка - 4.75
kvadro
11 / 9 / 1
Регистрация: 12.03.2012
Сообщений: 127
15.11.2013, 15:08     const float & #1
Заметил что часто передают и возвращают const float & ( например в мат либах ), вместо простой передачи значения.

Возникает вопрос: В чём плюс использования const float & вместо обычного float?
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
15.11.2013, 21:37     const float & #61
Цитата Сообщение от castaway Посмотреть сообщение
Так не замеряют.
Неужели? А как тогда?

Добавлено через 1 минуту
Кликните здесь для просмотра всего текста
Bash
user@linuxmint ~/Рабочий стол $ g++ game.cpp -ogame
user@linuxmint ~/Рабочий стол $ ./game
ref val
----------------
4.76    5.61
4.75    5.6
4.76    5.6
4.77    5.59
4.8 5.6
4.8 5.6
4.85    5.59
4.88    5.6
5.1 6.84
4.94    5.65
----------------
ref: 48.41
val: 57.28
user@linuxmint ~/Рабочий стол $ g++ game.cpp -ogame -O
user@linuxmint ~/Рабочий стол $ ./game
ref val
----------------
0.64    0.63
0.63    0.64
0.63    0.63
0.63    0.63
0.64    0.63
0.63    0.64
0.63    0.63
0.63    0.63
0.64    0.63
0.63    0.64
----------------
ref: 6.33
val: 6.33
user@linuxmint ~/Рабочий стол $ g++ game.cpp -ogame -O1
user@linuxmint ~/Рабочий стол $ ./game
ref val
----------------
0.66    0.66
0.64    0.65
0.63    0.63
0.65    0.66
0.65    0.65
0.65    0.65
0.65    0.64
0.64    0.64
0.66    0.65
0.66    0.66
----------------
ref: 6.49
val: 6.49
user@linuxmint ~/Рабочий стол $ g++ game.cpp -ogame -O2
user@linuxmint ~/Рабочий стол $ ./game
ref val
----------------
0   0
0   0
0   0
0   0
0   0
0   0
0   0
0   0
0   0
0   0
----------------
ref: 0
val: 0
user@linuxmint ~/Рабочий стол $ g++ game.cpp -ogame -O3
user@linuxmint ~/Рабочий стол $ ./game
ref val
----------------
0   0
0   0
0   0
0   0
0   0
0   0
0   0
0   0
0   0
0   0
----------------
ref: 0
val: 0
user@linuxmint ~/Рабочий стол $
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
castaway
15.11.2013, 21:39
  #62

Не по теме:

Цитата Сообщение от programina Посмотреть сообщение
А как тогда?
Должны быть четкие критерии.

lowercase
15.11.2013, 21:45
  #63

Не по теме:

Цитата Сообщение от kvadro Посмотреть сообщение
В чём плюс использования const float & вместо обычного float
можно разводить срачи на форумах, например

Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16829 / 5250 / 321
Регистрация: 30.03.2009
Сообщений: 14,139
Записей в блоге: 26
16.11.2013, 00:25     const float & #64
Цитата Сообщение от programina Посмотреть сообщение
А здесь? Очень криво?
Ты хочешь замерить как работает передача параметра в функцию. В этом случае надо запрещать инлайн. Но смысл всего деяния в том числе и в том, что в боевом режиме с оптимизациями инлайн должен работать. А потому непонятно, чего твой тест меряет. В режиме с оптимизациями он вырождается в пустышку. Как вариант запрещать инлайн и включить оптимизации - тогда замеришь время передачи параметров (насколько я понял, конкретно тебя волнует в первую очередь именно этот аспект). Но пример, который был описан в посте #4 в первую очередь подразумевает наличие инлайна
kvadro
11 / 9 / 1
Регистрация: 12.03.2012
Сообщений: 127
16.11.2013, 03:58  [ТС]     const float & #65
Evg
Без оптимизаций инлайн не сработает, но значение по ссылке браться не будет ибо оно будет лежать в регистре, по сути выходит +1 инструкция. Разницы нет. Завтра спрошу у самого автора, и в случае успеха отпишусь тут.
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 11:54     const float & #66
Действительно, если вставить __attribute__ ((noinline)) перед названием функции, то по значению будет гораздо быстрее, чем по ссылке:
C++
#include <cstdio>
#include <ctime>
 
struct vec4 { float a[4]; };
 
// По ссылке
vec4 __attribute__ ((noinline)) ref(float &a, float &b, float &c, float &d) 
{ 
    vec4 v;
    v.a[0] = a;
    v.a[1] = b;
    v.a[2] = c;
    v.a[3] = d; 
    return v; 
}
// По значению
vec4 __attribute__ ((noinline)) val(float  a, float  b, float  c, float  d) 
{ 
    vec4 v;
    v.a[0] = a;
    v.a[1] = b;
    v.a[2] = c;
    v.a[3] = d; 
    return v; 
}
 
//vec4(*pref)(float &, float &, float &, float &) = ref;
//vec4(*pval)(float,   float,   float,   float  ) = val;
 
clock_t t;
long N = 100000000;
double sc = 1000000.0;
float x = 0.0;
float y = 0.0;
float z = 0.0;
float w = 0.0;
 
 
int main()
{
    vec4 vref;
    vec4 vval;
 
    for(int g = 0; g < 5; g++)
    {
        t = clock();
        for(int i = 0; i < N; i++) vref = ref(x, y, z, w);
        t = clock() - t;
        printf("ref: %2.2f\t", t/sc);
 
        t = clock();
        for(int i = 0; i < N; i++) vval = val(x, y, z, w);
        t = clock() - t;
        printf("val: %2.2f\n", t/sc);
    }
}


Добавлено через 42 секунды
Bash
user@linuxmint ~/Рабочий стол $ g++ test.cpp -otest -O3
user@linuxmint ~/Рабочий стол $ ./test
ref: 1.08   val: 0.38
ref: 1.10   val: 0.38
ref: 1.13   val: 0.38
ref: 1.10   val: 0.39
ref: 1.10   val: 0.38
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
16.11.2013, 12:54     const float & #67
Только ты одного не учла, -O3 имеет приоритет над __attribute__ ((noinline)).
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16829 / 5250 / 321
Регистрация: 30.03.2009
Сообщений: 14,139
Записей в блоге: 26
16.11.2013, 12:55     const float & #68
Цитата Сообщение от kvadro Посмотреть сообщение
но значение по ссылке браться не будет ибо оно будет лежать в регистре
Ссылка - это адрес. Если значение лежит в регистре - оно будет перемещено в стек. Без инлайна этот код будет работать заведомо медленнее. Инлайн может отсутствовать и в режиме с оптимизациями, если функция будет большого размера или определена в другом модуле. Поэтому для чистоты эксперимента в коротких тестах надо запрещать инлайн.

programina, тест теперь "хороший". В нем даже есть цикл. Цикл нужен как минимум по двум соображениям. Первая итерация цикла - разогрев (подкачка всех кодов и данных в кэш). Остальные итерации - чистая работа процессора. Несколько итераций нужны для усреднения времени из-за флуктуаций

На всякий случай в ref надо добавить const во все ссылки. На коротком примере это не должно влиять, но для чистоты эксперимента нужно сделать. Возможно, что время ref'а чуток улучшится
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
16.11.2013, 12:56     const float & #69
Хотя... нет, не имеет. Просто GCC генерирует какую-то ерунду..
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16829 / 5250 / 321
Регистрация: 30.03.2009
Сообщений: 14,139
Записей в блоге: 26
16.11.2013, 13:00     const float & #70
Кстати, чтобы сделать запрет инлайна на компиляторе не-gcc, то проще всего вызывать функцию через указатель на функцию. Такой код будет переносимым, в отличие от кода с __attribute__((noinline))
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
16.11.2013, 13:08     const float & #71
Всё логично. В случае с ссылкой не создаются новые переменные, в случае с обычной переменной приходится их копировать, а это дополнительные инструкции fld и fstp на каждую переменную.

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от Evg Посмотреть сообщение
то проще всего вызывать функцию через указатель на функцию
.., ну или сделать её рекурсивной)

programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 13:31     const float & #72
А здесь по ссылке быстрее
C++
#include <cstdio>
#include <ctime>
 
struct mat4 { float a[16]; };
 
/// По ссылке
mat4 __attribute__ ((noinline)) ref(
    const float &a, const float &b, const float &c, const float &d,
    const float &e, const float &f, const float &g, const float &h,
    const float &i, const float &j, const float &k, const float &l,
    const float &m, const float &n, const float &o, const float &p
) 
{ 
    mat4 mtrx;
    mtrx.a[ 0] = a; mtrx.a[ 1] = b; mtrx.a[ 2] = c; mtrx.a[ 3] = d; 
    mtrx.a[ 4] = a; mtrx.a[ 5] = b; mtrx.a[ 6] = c; mtrx.a[ 7] = d; 
    mtrx.a[ 8] = a; mtrx.a[ 9] = b; mtrx.a[10] = c; mtrx.a[11] = d; 
    mtrx.a[12] = a; mtrx.a[13] = b; mtrx.a[14] = c; mtrx.a[15] = d; 
    return mtrx; 
}
/// По значению
mat4 __attribute__ ((noinline)) val(
    float a, float b, float c, float d,
    float e, float f, float g, float h,
    float i, float j, float k, float l,
    float m, float n, float o, float p
) 
{ 
    mat4 mtrx;
    mtrx.a[ 0] = a; mtrx.a[ 1] = b; mtrx.a[ 2] = c; mtrx.a[ 3] = d; 
    mtrx.a[ 4] = a; mtrx.a[ 5] = b; mtrx.a[ 6] = c; mtrx.a[ 7] = d; 
    mtrx.a[ 8] = a; mtrx.a[ 9] = b; mtrx.a[10] = c; mtrx.a[11] = d; 
    mtrx.a[12] = a; mtrx.a[13] = b; mtrx.a[14] = c; mtrx.a[15] = d; 
    return mtrx; 
}
 
/*
// Указатель на функцию "по-ссылке"
mat4(*pref)(
    const float&,const float&,const float&,const float&,  
    const float&,const float&,const float&,const float&,  
    const float&,const float&,const float&,const float&,  
    const float&,const float&,const float&,const float&
) = ref;
 
// Указатель на функцию "по-значению"
mat4(*pval)(
    float,float,float,float,  
    float,float,float,float,  
    float,float,float,float,  
    float,float,float,float
) = val;
*/
 
// глобальная дата
clock_t t;
long N = 100000000;
double sc = 1000000.0;
float a = 0.0;
float b = 0.0;
float c = 0.0;
float d = 0.0;
float e = 0.0;
float f = 0.0;
float g = 0.0;
float h = 0.0;
float i = 0.0;
float j = 0.0;
float k = 0.0;
float l = 0.0;
float m = 0.0;
float n = 0.0;
float o = 0.0;
float p = 0.0;
 
 
int main()
{
    mat4 mref;
    mat4 mval;
 
    for(int g = 0; g < 4; g++)
    {
        t = clock();
        for(int i = 0; i < N; i++) mref = ref(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p);
        t = clock() - t;
        printf("ref: %2.2f\t", t/sc);
 
        t = clock();
        for(int i = 0; i < N; i++) mval = val(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p);
        t = clock() - t;
        printf("val: %2.2f\n", t/sc);
    }
}
Bash
user@linuxmint ~/Рабочий стол $ g++ test.cpp -otest -O3
user@linuxmint ~/Рабочий стол $ ./test
ref: 0.64   val: 0.80
ref: 0.65   val: 0.80
ref: 0.63   val: 0.77
ref: 0.63   val: 0.80
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
16.11.2013, 13:34     const float & #73
По ссылке всегда должно быть быстрее. Главное правильно построить тест.
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 13:34     const float & #74
А если убрать __attribute__ ((noinline)) и вызывать функции через указатель на функцию, то по значению снова быстрее:
Bash
user@linuxmint ~/Рабочий стол $ g++ test.cpp -otest -O3
user@linuxmint ~/Рабочий стол $ ./test
ref: 1.12   val: 0.77
ref: 1.15   val: 0.78
ref: 1.11   val: 0.77
ref: 1.16   val: 0.80
Добавлено через 22 секунды
castaway, может все таки -O3 влияет?
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
16.11.2013, 13:35     const float & #75
Цитата Сообщение от castaway Посмотреть сообщение

Не по теме:

.., ну или сделать её рекурсивной)

Главное, чтобы при этом constexpr не стояло.
kvadro
11 / 9 / 1
Регистрация: 12.03.2012
Сообщений: 127
16.11.2013, 13:38  [ТС]     const float & #76
ref: 1.08 val: 0.38
ref: 1.10 val: 0.38
ref: 1.13 val: 0.38
ref: 1.10 val: 0.39
ref: 1.10 val: 0.38
А у меня:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ g++ main.cpp -o test
$ ./test
ref: 0.84   val: 0.87
ref: 0.84   val: 0.87
ref: 0.84   val: 0.87
ref: 0.84   val: 0.87
ref: 0.84   val: 0.89
 
$ g++ main.cpp -o test -O3
$ ./test
ref: 0.23   val: 0.23
ref: 0.23   val: 0.23
ref: 0.23   val: 0.22
ref: 0.23   val: 0.23
ref: 0.23   val: 0.23
 
$ clang++ main.cpp -o test -O3
$ ./test
ref: 0.00   val: 0.00
ref: 0.00   val: 0.00
ref: 0.00   val: 0.00
ref: 0.00   val: 0.00

ref: 0.64 val: 0.80
ref: 0.65 val: 0.80
ref: 0.63 val: 0.77
ref: 0.63 val: 0.80
И здесь наоборот:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ g++ main.cpp -o test
$ ./test
ref: 1.91   val: 1.63
ref: 1.95   val: 1.63
ref: 1.89   val: 1.74
ref: 1.95   val: 1.64
 
$ g++ main.cpp -o test -O3
$ ./test
ref: 0.48   val: 0.48
ref: 0.48   val: 0.48
ref: 0.48   val: 0.48
ref: 0.50   val: 0.48
 
$ clang++ main.cpp -o test -O3
$ ./test
ref: 0.51   val: 0.50
ref: 0.50   val: 0.50
ref: 0.50   val: 0.50
ref: 0.51   val: 0.51
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
16.11.2013, 13:42     const float & #77

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
Главное, чтобы при этом constexpr не стояло.
Хотел бы я на это посмотреть)

programina, можешь кинуть исполняемый файл в виде zip-архива, где по значению быстрее?
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 13:53     const float & #78

Цитата Сообщение от programina Посмотреть сообщение
mtrx.a[ 0] = a; mtrx.a[ 1] = b; mtrx.a[ 2] = c; mtrx.a[ 3] = d;
mtrx.a[ 4] = a; mtrx.a[ 5] = b; mtrx.a[ 6] = c; mtrx.a[ 7] = d;
Добавлено через 5 минут
Без указателя, но с аттрибутом __attribute__ ((noinline))
Bash
user@linuxmint ~/Рабочий стол $ g++ test.cpp -otest -O3
user@linuxmint ~/Рабочий стол $ ./test
ref: 0.79   val: 0.97
ref: 0.79   val: 0.99
ref: 0.79   val: 1.00
ref: 0.79   val: 1.00
С указателем, но без аттрибута __attribute__ ((noinline))
Bash
user@linuxmint ~/Рабочий стол $ g++ test.cpp -otest -O3
user@linuxmint ~/Рабочий стол $ ./test
ref: 1.48   val: 0.98
ref: 1.51   val: 0.97
ref: 1.49   val: 0.96
ref: 1.51   val: 0.98
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 13:55     const float & #79
Цитата Сообщение от castaway Посмотреть сообщение

Не по теме:

Хотел бы я на это посмотреть)

programina, можешь кинуть исполняемый файл в виде zip-архива, где по значению быстрее?
test.zip
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.11.2013, 13:56     const float &
Еще ссылки по теме:

C++ const& и const* в имени функции
(const string &) C++
#define PI or static const float PI C++

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

Или воспользуйтесь поиском по форуму:
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 13:56     const float & #80
Кликните здесь для просмотра всего текста
C++
// g++ test.cpp -otest -O3
 
#include <cstdio>
#include <ctime>
 
struct mat4 { float a[16]; };
 
/// По ссылке
mat4 /*__attribute__ ((noinline))*/ ref(
    const float &a, const float &b, const float &c, const float &d,
    const float &e, const float &f, const float &g, const float &h,
    const float &i, const float &j, const float &k, const float &l,
    const float &m, const float &n, const float &o, const float &p
) 
{ 
    mat4 mtrx;
    mtrx.a[ 0] = a; mtrx.a[ 1] = b; mtrx.a[ 2] = c; mtrx.a[ 3] = d; 
    mtrx.a[ 4] = e; mtrx.a[ 5] = f; mtrx.a[ 6] = g; mtrx.a[ 7] = h; 
    mtrx.a[ 8] = i; mtrx.a[ 9] = j; mtrx.a[10] = k; mtrx.a[11] = l; 
    mtrx.a[12] = m; mtrx.a[13] = n; mtrx.a[14] = o; mtrx.a[15] = p; 
    return mtrx; 
}
/// По значению
mat4 /*__attribute__ ((noinline))*/ val(
    float a, float b, float c, float d,
    float e, float f, float g, float h,
    float i, float j, float k, float l,
    float m, float n, float o, float p
) 
{ 
    mat4 mtrx;
    mtrx.a[ 0] = a; mtrx.a[ 1] = b; mtrx.a[ 2] = c; mtrx.a[ 3] = d; 
    mtrx.a[ 4] = e; mtrx.a[ 5] = f; mtrx.a[ 6] = g; mtrx.a[ 7] = h; 
    mtrx.a[ 8] = i; mtrx.a[ 9] = j; mtrx.a[10] = k; mtrx.a[11] = l; 
    mtrx.a[12] = m; mtrx.a[13] = n; mtrx.a[14] = o; mtrx.a[15] = p; 
    return mtrx; 
}
 
 
// Указатель на функцию "по-ссылке"
mat4(*pref)(
    const float&,const float&,const float&,const float&,  
    const float&,const float&,const float&,const float&,  
    const float&,const float&,const float&,const float&,  
    const float&,const float&,const float&,const float&
) = ref;
 
// Указатель на функцию "по-значению"
mat4(*pval)(
    float,float,float,float,  
    float,float,float,float,  
    float,float,float,float,  
    float,float,float,float
) = val;
 
 
// глобальная дата
clock_t t;
long N = 100000000;
double sc = 1000000.0;
float a = 0.0;
float b = 0.0;
float c = 0.0;
float d = 0.0;
float e = 0.0;
float f = 0.0;
float g = 0.0;
float h = 0.0;
float i = 0.0;
float j = 0.0;
float k = 0.0;
float l = 0.0;
float m = 0.0;
float n = 0.0;
float o = 0.0;
float p = 0.0;
 
 
int main()
{
    mat4 mref;
    mat4 mval;
 
    for(int g = 0; g < 4; g++)
    {
        t = clock();
        for(int i = 0; i < N; i++) mref = pref(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p);
        t = clock() - t;
        printf("ref: %2.2f\t", t/sc);
 
        t = clock();
        for(int i = 0; i < N; i++) mval = pval(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p);
        t = clock() - t;
        printf("val: %2.2f\n", t/sc);
    }
}
Yandex
Объявления
16.11.2013, 13:56     const float &
Ответ Создать тему
Опции темы

Текущее время: 18:57. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru