Форум программистов, компьютерный форум 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)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16844 / 5265 / 323
Регистрация: 30.03.2009
Сообщений: 14,159
Записей в блоге: 26
16.11.2013, 13:58     const float & #81
Цитата Сообщение от programina Посмотреть сообщение
А здесь по ссылке быстрее
Сдаётся мне, что тут дело в программных соглашениях. Когда параметров мало, то они передаются на регистрах, когда много - в стеке. Возможно, что на intel'е скопировать плавающее значение в стек занимает больше времени, чем целочисленное (указатель). Но тут я могу только ткнуть пальцем в небо, я плохо знаю intel'овскую систему команд

Добавлено через 1 минуту
Или доставание параметров из стека внутри вызываемой функции

programina, попробуй в примере с большим количеством параметров (пост 72) выкинуть внутренности функций ref и val и сделать их void. Т.е. чтобы кроме передачи параметров ничего не было
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
programina
16.11.2013, 14:01
  #82

Не по теме:

У меня AMD A10-4600M with Turbo CORE Technology up to 3.20 GHz

castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
16.11.2013, 14:21     const float & #83
programina, в твоей программе используются SIMD-инструкции, от этого такой резонанс. Еще раз повторюсь: тесты так не делают. Хотя бы убери флаг -O3.
kvadro
11 / 9 / 1
Регистрация: 12.03.2012
Сообщений: 127
16.11.2013, 14:30  [ТС]     const float & #84
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
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <ctime>
 
// ============================================================================
struct Vec3
{
    Vec3( const float xx, const float yy, const float zz )
    {
        x = xx;
        y = yy;
        z = zz;
        pad = 0.F;
    }
    
    union
    {
        struct { float x, y, z, pad; };
    };
};
 
// ============================================================================
struct Vec3Ref
{
    Vec3Ref( const float &xx, const float &yy, const float &zz )
    {
        x = xx;
        y = yy;
        z = zz;
        pad = 0.F;
    }
    
    union
    {
        struct { float x, y, z, pad; };
    };
};
 
// ============================================================================
 
Vec3 operator*( const Vec3 &v, const float s )
{
    return Vec3( v.x * s, v.y * s,  v.z * s );
}
 
Vec3Ref operator*( const Vec3Ref &v, const float &s )
{
    return Vec3Ref( v.x * s, v.y * s,  v.z * s );
}
 
// ============================================================================
 
clock_t t;
double sc = 1000000.0;
const long N = 100000000;
 
int main()
{
    srand( static_cast< unsigned >( time( 0 ) ) );
    
    float x = static_cast< float >( rand() ) / static_cast< float >( RAND_MAX / 100000 );
    float y = static_cast< float >( rand() ) / static_cast< float >( RAND_MAX / 100000 );
    float z = static_cast< float >( rand() ) / static_cast< float >( RAND_MAX / 100000 );
    
    Vec3 vec( x, y, z );
    Vec3Ref vecref( x, y, z );
    
    for( int i = 0; i < 4; i++ )
    {
        t = clock();
        for( int j = 0; j < N; j++ ) { Vec3 vec_ = vec * i; }
        t = clock() - t;
        std::cout << "val: " << std::setprecision(2) << t/sc << "\t";
    
        t = clock();
        for( int j = 0; j < N; j++ ) { Vec3Ref vecref_ = vecref * i; }
        t = clock() - t;
        std::cout << "ref: " << std::setprecision(2) << t/sc << std::endl;
    
    
    }
}

$ g++ main.cpp -o test

val: 1.1 ref: 1.2
val: 1.1 ref: 1.2
val: 1.1 ref: 1.2
val: 1.1 ref: 1.2

$ clang++ main.cpp -o test

val: 1.1 ref: 1.4
val: 1.1 ref: 1.3
val: 1.1 ref: 1.3
val: 1.1 ref: 1.5

$ g++ main.cpp -o test -O3 -fno-inline

val: 0.68 ref: 0.73
val: 0.67 ref: 0.73
val: 0.68 ref: 0.73
val: 0.68 ref: 0.75
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 14:41     const float & #85
Цитата Сообщение от Evg Посмотреть сообщение
Когда параметров мало, то они передаются на регистрах, когда много - в стеке.
Увеличила число параметров до 52 (два английских алфавита), сейчас по значению быстрее.
Кликните здесь для просмотра всего текста

C++
#include <cstdio>
#include <ctime>
 
struct mat4 { float a[52]; };
 
/// По ссылке
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,
    const float &q, const float &r, const float &s, const float &t,
    const float &u, const float &v, const float &w, const float &x,
    const float &y, const float &z,
    const float &a1, const float &b1, const float &c1, const float &d1,
    const float &e1, const float &f1, const float &g1, const float &h1,
    const float &i1, const float &j1, const float &k1, const float &l1,
    const float &m1, const float &n1, const float &o1, const float &p1,
    const float &q1, const float &r1, const float &s1, const float &t1,
    const float &u1, const float &v1, const float &w1, const float &x1,
    const float &y1, const float &z1
) 
{ 
    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; 
    mtrx.a[16] = q; mtrx.a[17] = r; mtrx.a[18] = s; mtrx.a[19] = t; 
    mtrx.a[20] = u; mtrx.a[21] = v; mtrx.a[22] = w; mtrx.a[23] = x; 
    mtrx.a[24] = y; mtrx.a[25] = z;
    mtrx.a[26] = a1; mtrx.a[27] = b1; mtrx.a[28] = c1; mtrx.a[29] = d1; 
    mtrx.a[30] = e1; mtrx.a[31] = f1; mtrx.a[32] = g1; mtrx.a[33] = h1; 
    mtrx.a[34] = i1; mtrx.a[35] = j1; mtrx.a[36] = k1; mtrx.a[37] = l1; 
    mtrx.a[38] = m1; mtrx.a[39] = n1; mtrx.a[40] = o1; mtrx.a[41] = p1; 
    mtrx.a[42] = q1; mtrx.a[43] = r1; mtrx.a[44] = s1; mtrx.a[45] = t1; 
    mtrx.a[46] = u1; mtrx.a[47] = v1; mtrx.a[48] = w1; mtrx.a[49] = x1; 
    mtrx.a[50] = y1; mtrx.a[51] = z1;
    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,
    float q, float r, float s, float t,
    float u, float v, float w, float x,
    float y, float z,   
    float a1, float b1, float c1, float d1,
    float e1, float f1, float g1, float h1,
    float i1, float j1, float k1, float l1,
    float m1, float n1, float o1, float p1,
    float q1, float r1, float s1, float t1,
    float u1, float v1, float w1, float x1,
    float y1, float z1  
) 
{ 
    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; 
    mtrx.a[16] = q; mtrx.a[17] = r; mtrx.a[18] = s; mtrx.a[19] = t; 
    mtrx.a[20] = u; mtrx.a[21] = v; mtrx.a[22] = w; mtrx.a[23] = x; 
    mtrx.a[24] = y; mtrx.a[25] = z;
    mtrx.a[26] = a1; mtrx.a[27] = b1; mtrx.a[28] = c1; mtrx.a[29] = d1; 
    mtrx.a[30] = e1; mtrx.a[31] = f1; mtrx.a[32] = g1; mtrx.a[33] = h1; 
    mtrx.a[34] = i1; mtrx.a[35] = j1; mtrx.a[36] = k1; mtrx.a[37] = l1; 
    mtrx.a[38] = m1; mtrx.a[39] = n1; mtrx.a[40] = o1; mtrx.a[41] = p1; 
    mtrx.a[42] = q1; mtrx.a[43] = r1; mtrx.a[44] = s1; mtrx.a[45] = t1; 
    mtrx.a[46] = u1; mtrx.a[47] = v1; mtrx.a[48] = w1; mtrx.a[49] = x1; 
    mtrx.a[50] = y1; mtrx.a[51] = z1;
    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&,
    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&,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&,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,
    float,float,float,float,
    float,float,float,float,
    float,float,
    float,float,float,float,  
    float,float,float,float,  
    float,float,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, b = 0.0, c = 0.0, d = 0.0;
float e = 0.0, f = 0.0, g = 0.0, h = 0.0;
float i = 0.0, j = 0.0, k = 0.0, l = 0.0;
float m = 0.0, n = 0.0, o = 0.0, p = 0.0;
float q = 0.0, r = 0.0, s = 0.0, t = 0.0;
float u = 0.0, v = 0.0, w = 0.0, x = 0.0;
float y = 0.0, z = 0.0;
 
float a1 = 0.0, b1 = 0.0, c1 = 0.0, d1 = 0.0;
float e1 = 0.0, f1 = 0.0, g1 = 0.0, h1 = 0.0;
float i1 = 0.0, j1 = 0.0, k1 = 0.0, l1 = 0.0;
float m1 = 0.0, n1 = 0.0, o1 = 0.0, p1 = 0.0;
float q1 = 0.0, r1 = 0.0, s1 = 0.0, t1 = 0.0;
float u1 = 0.0, v1 = 0.0, w1 = 0.0, x1 = 0.0;
float y1 = 0.0, z1 = 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,q,r,s,t,u,v,w,x,y,z,a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1,u1,v1,w1,x1,y1,z1);
        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,q,r,s,t,u,v,w,x,y,z,a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1,u1,v1,w1,x1,y1,z1);
        T = clock() - T;
        printf("val: %2.2f\n", T/sc);
    }
}

Bash
user@linuxmint ~/Рабочий стол $ g++ test.cpp -otest -O3
user@linuxmint ~/Рабочий стол $ ./test
ref: 4.28   val: 3.63
ref: 4.26   val: 3.65
ref: 4.26   val: 3.63
ref: 4.27   val: 3.65
Добавлено через 9 минут
Цитата Сообщение от castaway Посмотреть сообщение
Хотя бы убери флаг -O3
А без флага вот так по ссылке снова быстрее:
Bash
user@linuxmint ~/Рабочий стол $ g++ test.cpp -otest
user@linuxmint ~/Рабочий стол $ ./test
ref: 7.77   val: 7.98
ref: 7.55   val: 7.98
ref: 7.56   val: 7.99
ref: 7.57   val: 7.98
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
16.11.2013, 15:00     const float & #86

Не по теме:

Цитата Сообщение от Evg Посмотреть сообщение
Когда параметров мало, то они передаются на регистрах, когда много - в стеке.
Существует такое понятие "соглашения вызовов".



Добавлено через 19 минут
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <chrono>
 
using namespace std;
 
#define ITERATIONS 10000
 
#define MEASURE( func )                                             \
    {                                                               \
        chrono::system_clock::time_point a, b;                      \
                                                                    \
        /* warm up */                                               \
        for ( unsigned i = 0; i < ITERATIONS; i++ ) {               \
            func();                                                 \
        }                                                           \
                                                                    \
        /* start benchmark */                                       \
        a = chrono::system_clock::now();                            \
        for ( unsigned i = 0; i < ITERATIONS; i++ ) {               \
            for ( unsigned j = 0; j < ITERATIONS; j++ ) {           \
                func();                                             \
            }                                                       \
        }                                                           \
        b = chrono::system_clock::now();                            \
        cout << #func << " \t: " << chrono::duration_cast< chrono::milliseconds >( b - a ).count() << " ms." << endl;   \
    }
 
 
//static float 
static float the_array[10];
 
void func_ref( float & _0, float & _1, float & _2, float & _3, float & _4, float & _5, float & _6, float & _7, float & _8, float & _9 ) {
    the_array[0] = _0;
    the_array[1] = _1;
    the_array[2] = _2;
    the_array[3] = _3;
    the_array[4] = _4;
    the_array[5] = _5;
    the_array[6] = _6;
    the_array[7] = _7;
    the_array[8] = _8;
    the_array[9] = _9;
}
 
void func_val( float _0, float _1, float _2, float _3, float _4, float _5, float _6, float _7, float _8, float _9 ) {
    the_array[0] = _0;
    the_array[1] = _1;
    the_array[2] = _2;
    the_array[3] = _3;
    the_array[4] = _4;
    the_array[5] = _5;
    the_array[6] = _6;
    the_array[7] = _7;
    the_array[8] = _8;
    the_array[9] = _9;
}
 
static float v[10];
 
void test_ref() {
    func_ref( v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9] );
}
 
void test_val() {
    func_val( v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9] );
}
 
int main()
{
    for ( int i = 0; i < 10; i++ ) v[i] = static_cast<float>(i ^ 123);
    MEASURE( test_val );
    MEASURE( test_ref );
    return 0;
}
Bash
1
2
test_val    : 1349 ms.
test_ref    : 1721 ms.
Не знаю почему так, но выяснить хочу..
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 15:10     const float & #87
Цитата Сообщение от castaway Посмотреть сообщение
Bash
test_val    : 1349 ms.
test_ref    : 1721 ms.
Не знаю почему так, но выяснить хочу..
Bash
user@linuxmint ~/Рабочий стол $ g++ test.cpp -otest -std=c++11
user@linuxmint ~/Рабочий стол $ ./test
test_val    : 1658 ms.
test_ref    : 1194 ms.
Добавлено через 1 минуту
Я вообще ничего не понимаю
kvadro
11 / 9 / 1
Регистрация: 12.03.2012
Сообщений: 127
16.11.2013, 15:12  [ТС]     const float & #88
Я вообще ничего не понимаю
AMD vs Intel
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 15:14     const float & #89
Цитата Сообщение от kvadro Посмотреть сообщение
AMD vs Intel
Сейчас проверю код castaway на core i7
kvadro
11 / 9 / 1
Регистрация: 12.03.2012
Сообщений: 127
16.11.2013, 15:23  [ТС]     const float & #90
i7 с -O3 -fno-inline

test_val : 587 ms.
test_ref : 522 ms.
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
16.11.2013, 15:28     const float & #91
Проверила на intel core i7, по ссылке попрежнему быстрее, но всего в 1.2 - 1.3 раза.
Tulosba
16.11.2013, 15:28
  #92

Не по теме:

Цитата Сообщение от castaway Посмотреть сообщение
Хотел бы я на это посмотреть)
C++
1
2
3
4
constexpr long long int f( int i )
{
    return i ? f(i-1)*i : 1;
}

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.11.2013, 15:32     const float &
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
castaway
16.11.2013, 15:32     const float &
  #93

Не по теме:

Цитата Сообщение от kvadro Посмотреть сообщение
AMD vs Intel
Ну это тут явно не при чем..

Yandex
Объявления
16.11.2013, 15:32     const float &
Ответ Создать тему
Опции темы

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