Bởi vì các hàm gettime đều tương đối, nên mình với test 100 lần, mỗi lần lặp 50 triệu lần rồi mới lấy kết quả để giảm sai số.
Tuy nhiên cả 2 lần test đều cho kết quả ngang nhau.
Asm trên là đoạn asm cho cả một hàm xử lý dữ lieu bên trong 1 object nên nó mới nhiều mã asm như vậy.
Bản than I++ hay ++I cũng chỉ 4 asm lệnh thôi.
Khác biệt giữa i++ và ++i
đo tốc độ xài std::chrono::stead_clock::now()
ấy, xài GetTickCount làm gì
mà thật khó tin cái proc1 và proc2 ko bị optimized thành 1 dòng code? 1 vòng for với i chạy từ 0 tới 1 giá trị define cho trước, val
chả làm gì trong 49.999999 triệu lần trước chỉ cần giá trị sau cùng, vậy mà ko optimize được?
à nó còn phải ++ thêm giá trị cho data, vậy chắc ko optimize được @_@ Chắc là do thời gian tương đối thôi =)
edit: chạy thử thấy đúng là val = data[i]++
nhanh hơn thật, nhưng khi để data[i]++
ko mà ko gán cho val
thì lại xấp xỉ như nhau, có gì uẩn khúc ở đây, oan ức quá =)
đổi thành val += ...
thì ++i nhanh hơn chút xíu Vậy cái vấn đề val = ở đây là sao
edit:
╭╴C:\Users\tri\Desktop
╰╼ a
TOTAL 100 TIMES MODE 2: ------------------------------------------------
++I :962060
I++ :973266
TOTAL 100 TIMES MODE 1------------------------------------------------
I++ :964262
++I :967017
chắc hên xui, 10 lần chạy cũng có 1 lần ++i nhanh hơn, nhưng hoàn toàn chậm hơn trên MSVC ko biết tại sao
Proc1 và proc2 thực hiện 2 cách khác nhau nên không thể optimize thành 1 là đúng rồi.
Việc gán val thực hiện mà không optimize là nó làm đúng, nhiều khi cần như vậy tùy yêu cầu thôi.
Thời gian có thể nhanh chậm hơn nhau chút xíu vì bản chat nó như vậy rồi (xung CPU lúc cao lúc thấp,CPU switch nhiều công việc mỗi lúc lại khác nhau…)
Nhưng kết quả same same nhau cùng với việc view asm thì chắc là cũng đủ để thấy việc nhanh chậm hơn nhau giữa ++I và I++ là không có cơ sở.
Ở trên bạn disasm đã thấy việc thực hiện đều mất 4 lệnh asm. Chỉ cần vênh nhau 1 lệnh asm thì thời gian sẽ vênh nhau 20-25% rồi chứ không lệch 1 chút như vậy.
edit lần chót: đổi kiểu của data
và val
thành long long
sẽ thấy 2 chú chạy nhanh như nhau
TOTAL 100 TIMES MODE 2: ------------------------------------------------
++I :1818525
I++ :1833648
TOTAL 100 TIMES MODE 1------------------------------------------------
I++ :1796192
++I :1794913
Kết luận là ông MSVC gặp vấn đề lớn khi convert reference của biến. Nếu chạy trên OS 32-bit chắc nó sẽ như nhau, chạy trên OS 64-bit thì reference của ++i là 8 byte nên gây ra chậm hơn int 4 byte???
thử trên MSYS2 g++ thì thấy tốc độ tương đương nhau, có ông MS là có vấn đề vì cái ++i trả về reference ổng ko handle nổi @_@
hoặc có thể trên OS 64-bit thì load lên thanh ghi bằng cách nào đó bị biến thành 64-bit integer hết? Thử với char, short, int đều thấy ++i chậm hơn, chỉ có long long là như nhau @_@
Xử lý số độ rộng (số byte) khác nhau chắc là cũng khác nhau rồi.
Ví dụ CPU 32 bit xử lý long (64bit) hoặc double thì nó không xử lý cái rụp được mà phải xử lý từng phần.
Code dài miên man, mà MSVC cũng đâu có theo đúng C++ 100% chỉ là nghề tay trái thôi.
p/s: MSVC ko xài /O3 mà dùng /O2 /Ox /Os.
ông Dương từ C# bẻ lái sang C++ mà, nên xài con trỏ rồi cấp phát động tùm lum =) delete[] cũng quên nữa
Cái gì mà bẻ, code thì code C++, cũng đang nói C++ có nói gì đến C# đâu ?
Chả thấy delete trong desctructor kia kìa
Trước giã C/C++ xong thấy cực chết mới qua C# thôi.
delete
khác với delete[]
=) Nếu cấp phát động cho 1 phần tử new int
thì xài delete
, còn 1 mảng new int[...]
thì xài delete[]
. Trong test mode 1 với test mode 2 đều quên delete OBJ1; delete OBJ2;
, 400MB của mode 1 vẫn còn khi chạy mode 2.
xài std::vector
cho lành, xài new rồi delete chi cho khổ
Chỗ delete nhầm
Nhưng mà chỉ chú ý vào ++I với I++ nên không để tâm mấy cái đó.
cũng không có ý định resize nên dung kiểu đó cho lẹ
Test thế đã gần full RAM rồi mà vector nữa chắc chết @@.
lẹ đâu ko thấy, thấy phải viết dtor là 1, viết sai dtor là 2, quên delete OBJ trong testmode là 3 =) Cứ gọi Test OBJ1, OBJ2;
vô tư có cần phải cấp phát động đâu, cũng vì new delete cái data nên lại sợ phải new OBJ1 luôn, phải xài vector ngay từ đầu thì cứ vô tư rồi
#include <iostream>
#include <chrono>
#include <vector>
using namespace std;
using namespace std::chrono;
const int DATA_LENGHT = 10000000;
struct Test {
vector<long long> data;
long long val;
Test() : data(DATA_LENGHT + 1), val(0) {}
void proc1() { for (int i = 0; i < DATA_LENGHT; i++) val = data[i]++; }
void proc2() { for (int i = 0; i < DATA_LENGHT; ++i) val = ++data[i]; }
};
void testMode1(int loop=100)
{
Test obj1;
Test obj2;
long long totaltime1 = 0;
long long totaltime2 = 0;
for (int i = 0; i < loop; i++)
{
auto start = steady_clock::now();
obj1.proc1();
auto end = steady_clock::now();
totaltime1 += duration_cast<microseconds>(end - start).count();
start = steady_clock::now();
obj2.proc2();
end = steady_clock::now();
totaltime2 += duration_cast<microseconds>(end - start).count();
}
std::cout << "TOTAL " << loop << " MODE 1 -------------------- " << endl;
std::cout << "I++ :" << totaltime1 << "us" << endl;
std::cout << "++I :" << totaltime2 << "us" << endl;
}
void testMode2(int loop=100)
{
Test obj1;
Test obj2;
long long totaltime1 = 0;
long long totaltime2 = 0;
for (int i = 0; i < loop; i++)
{
auto start = steady_clock::now();
obj1.proc2();
auto end = steady_clock::now();
totaltime2 += duration_cast<microseconds>(end - start).count();
start = steady_clock::now();
obj2.proc1();
end = steady_clock::now();
totaltime1 += duration_cast<microseconds>(end - start).count();
}
std::cout << "TOTAL " << loop << " MODE 2 -------------------- " << endl;
std::cout << "I++ :" << totaltime1 << "us" << endl;
std::cout << "++I :" << totaltime2 << "us" << endl;
}
int main()
{
testMode1();
testMode2();
}
ngắn gọn súc tích chính xác tới từng microsecond (nhầm qua mili @_@)
Chỗ code dài là phải xem xem nó làm gì trong code đó.
Thằng MSVC nó vẫn + và gán val. Chắc thằng G++ nó tang thẳng val = 50000000 luôn mới 4 lệnh. Cái này hồi làm QT Framework thấy rồi
Ăn bớt hết Enter của người ta ::))
a ơi. giải thuật toán này dùm e vs ạ. em làm như trên vẫn sai. test chương trình a+b thì ra 24.
giải thích e vs ạ. bị lộn tùng phèo chỗ này
int a=7, b=8;
a++;
a=a+(b- -); - -b;
a- -;
a=(- -a)+(- -b);
printf("Tong cua a va b la: %d", a+b);
Undefined behavior ở dòng
rồi nhé, nghĩ làm gì nữa.
Nói cách khác, i++ là bạn tăng biến lên 1 rồi thực hiện phép tính, còn ++i thì bạn tính rồi mới +1
hình như nói ngược rồi à? :V
nhầm rồi bạn, trong toán tử một ngôi prefix ++i
tính trước cuối cùng mới đến postfix i++
int a=7, b=8;
a++; //a = 8
a=a+(b--); //b = 7 a = 16
--b; // b = 6
a--; //a = 15
a=(--a)+(--b); // a = 19 và b = 5
System.out.println("Tong cua a va b la: %d" + (a+b)); // tổng 24