C++ 에는 절댓값을 구할 수 있는 함수 abs 함수가 있습니다.
이 함수를 이용하게 되면 함수 호출에 대한 페널티를 받기 때문에 if 혹은 수의 특성을 이용해서 구해 시간을 줄일 수 있습니다.
#define bit_abs(x) ~x + 1
정수형인 int, long long의 경우 왼쪽 끝의 비트가 부호를 나타내므로 0x80000000 & x를 통해 부호를 알 수 있습니다.
#define bit_fabs(x) (*reinterpret_cast<std::uint64_t*>(&x)) &= 0x7fffffffffffffff
실수형 double, float의 경우 메모리 기준으로 64, 32 비트 형식으로 타입 캐스팅 해준 후 최상단 비트가 sign을 나타내므로 0x7ffffffff & x을 통해 부호를 변경할 수 있습니다.
비트를 활용하거나 if문을 활용하는 것이 abs, fabs보다 더 빠른 것을 볼 수 있습니다. 비트와 if문을 활용하는 경우 거의 비슷한 결과를 얻을 수 있었습니다.
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
|
#include <iostream>
#include <algorithm>
#include <random>
#include <ctime>
#include <Windows.h>
#define MAX 4000000
#define bit_abs(x) x&0x80000000 ? -(x) : x
#define bit_fabs(x) (*reinterpret_cast<std::uint64_t*>(&x)) &= 0x7fffffffffffffff
using namespace std;
template<typename T = int>
void use_if(T ary[]) {
for (int i = 0; i < MAX; i++) {
if (ary[i] < 0)
ary[i] = -ary[i];
}
}
template<typename T = int>
void use_bitop(T ary[]) {
for (int i = 0; i < MAX; i++)
ary[i] = bit_abs(ary[i]);
}
template<typename T = int>
void use_bitif(T ary[]) {
for (int i = 0; i < MAX; i++)
if (ary[i] & 0x80000000)
ary[i] = -ary[i];
}
template<typename T = int>
void use_abs(T ary[]) {
for (int i = 0; i < MAX; i++)
ary[i] = abs(ary[i]);
}
template<typename T = double>
void use_fabs(T ary[]) {
for (int i = 0; i < MAX; i++)
ary[i] = fabs(ary[i]);
}
template<typename T = double>
void use_bit_fabs(T ary[]) {
for (int i = 0; i < MAX; i++)
bit_fabs(ary[i]);
}
template<typename T, typename F>
void query(T ary[], F f, const char *s) {
T tmp[MAX];
memcpy(tmp, ary, sizeof ary);
double time;
bool b;
__int64 freq, start, end;
BOOL condition;
if (condition = QueryPerformanceFrequency((_LARGE_INTEGER*)&freq))
QueryPerformanceCounter((_LARGE_INTEGER*)&start);
f(tmp);
if (condition) {
QueryPerformanceCounter((_LARGE_INTEGER*)&end);
time = (float)((double)(end - start) / freq * 1000);
printf("use %s => time : %lf\n", s, time);
}
}
int main() {
mt19937 gen(12345);
/*uniform_int_distribution<int> dist(-0x7fffffff, 0x7fffffff);
int ary[MAX], tmp[MAX];
for (int i = 0; i < MAX; i++) {
ary[i] = dist(gen);
}
query(ary, &use_bitop<int>, "bit");
query(ary, &use_bitif<int>, "bitif");
query(ary, &use_if<int>, "if");
query(ary, &use_abs<int>, "abs");*/
uniform_real_distribution<double>dist(-0x7fffffff, 0x7fffffff);
double ary[MAX], tmp[MAX];
for (int i = 0; i < MAX; i++) {
ary[i] = dist(gen);
}
query(ary, &use_if<double>, "if");
query(ary, &use_bit_fabs<double>, "bit");
query(ary, &use_fabs<double>, "fabs");
}
|
cs |
반응형
'스터디 > C++' 카테고리의 다른 글
[C++] struct, pair 비교 (0) | 2020.12.17 |
---|