簡體   English   中英

當用文字替換變量用法時,程序會減慢很多速度,為什么呢?

[英]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函數不再被內聯,盡管checkLeftEdgecheckTopEdge仍然存在。

代碼的修改部分似乎沒有太大變化:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM