[英]Program slowing down a lot when replaced variable usage with a literal, why?
我正在嘗試針對此挑戰優化解決方案。 在注意到其他解決方案之一使用了一個很好的技巧后,將size
更改為編譯時模板參數,然后我想自己檢查一下它將如何加速代碼。
我從帶有發行版配置的MSVC2013進行編譯。 這是原始代碼:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using std::cout;
using std::endl;
typedef std::vector<char*> Board;
int size;
void rotate(char *str){
char temp = str[0];
str[0] = str[1];
str[1] = str[2];
str[2] = str[3];
str[3] = temp;
}
inline char fastToLower(char c){ //actually it's toUpper but whatever
return (c - 65) % 32;
}
bool checkLeftEdge(Board::iterator begin, Board::iterator right){
if ((right - begin) % size == 0)
return true;
auto left = right - 1;
char c1 = (*right)[3], c2 = (*left)[1];
return fastToLower(c1) == fastToLower(c2) && c1 != c2;
}
bool checkTopEdge(Board::iterator begin, Board::iterator bottom){
auto top = bottom - size;
if (top < begin)
return true;
char c1 = (*bottom)[0], c2 = (*top)[2];
return fastToLower(c1) == fastToLower(c2) && c1 != c2;
}
bool isLastElementValid(Board::iterator begin, Board::iterator last){
return
checkTopEdge(begin, last) &&
checkLeftEdge(begin, last);
}
bool recurse(Board::iterator begin, Board::iterator end, Board::iterator len){
if (len == end)
return true;
for (auto it = len; it != end; ++it){
std::swap(*len, *it);
for (int j = 0; j < 4; ++j){
if (isLastElementValid(begin, len)){
bool ret = recurse(begin, end, len + 1);
if (ret == true)
return ret;
}
rotate(*len);
}
std::swap(*len, *it);
}
return false;
}
void draw(const Board &board){
for (int y = 0; y < size; ++y){
cout << std::string(size * 4 + 1, '-') << endl;
for (int x = 0; x < size; ++x)
cout << "| " << board[to_index(x, y)][0] << " ";
cout << "|" << endl;
for (int x = 0; x < size; ++x)
cout << "|" << board[to_index(x, y)][3] << " " << board[to_index(x, y)][1];
cout << "|" << endl;
for (int x = 0; x < size; ++x)
cout << "| " << board[to_index(x, y)][2] << " ";
cout << "|" << endl;
}
cout << std::string(size * 4 + 1, '-') << endl;
cout << endl;
}
int main(){
std::ifstream in ("in.txt");
if (!in)
return 1;
in >> size;
Board board(size * size);
for (auto& ptr : board){
ptr = new char[4];
in.ignore();
in.read(ptr, 4);
}
auto success = recurse(board.begin(), board.end(), board.begin());
if (success)
draw(board);
for (auto& ptr : board)
delete []ptr;
std::cin.ignore();
std::cin.get();
}
使用這組樣本數據:
5
ckck
yYcc
YcCK
kKCM
CMKc
cKYC
kYcm
KYyY
Mccm
yKcm
mykK
MMCm
ckYC
ycmm
MmKM
kymc
KMMK
KcyM
kYck
YCKM
myYm
kYyY
CMKM
yYCM
YKyk
該程序運行了11.5秒。
當我更換
bool checkTopEdge(Board::iterator begin, Board::iterator bottom){
auto top = bottom - size;
同
auto top = bottom - 5;
該程序運行了不到10秒。
但是當我更換時:
bool checkLeftEdge(Board::iterator begin, Board::iterator right){
if ((right - begin) % size == 0)
同
if ((right - begin) % 5 == 0)
時間增加到16秒!
我已經看了一下反匯編,並注意到isLastElementValid
函數不再被內聯,盡管checkLeftEdge
和checkTopEdge
仍然存在。
代碼的修改部分似乎沒有太大變化:
0138136C mov eax,ecx
0138136E sub eax,esi
01381370 sar eax,2
01381373 cdq
01381374 idiv eax,ebx
01381376 test edx,edx
01381378 je recurse+0E2h (013813B2h)
具有5個字面量:
00B4133D mov eax,ecx
00B4133F mov esi,5
00B41344 sub eax,edx
00B41346 sar eax,2
00B41349 cdq
00B4134A idiv eax,esi
00B4134C test edx,edx
00B4134E je isLastElementValid+0CAh (0B4139Ah)
所以我的問題是:我看不到所做的更改如何導致程序變慢。 即使MSVC出於某種原因決定不再內聯其中一個功能,我也不敢相信僅此一項就導致運行時間增加了50%。
那實際上是由線性作用引起的。 我已經通過將__declspec(noinline)
添加到isLastElementValid進行了檢查,這確實造成了50%的損失。
用__forceinline
強制內聯解決了我的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.