简体   繁体   English

通过使用指针/引用,在C ++中使用向量加快计算速度

[英]Speeding up calculation using vectors in C++ by using pointers/references

Currently, I am making a C++ program that solves a sudoku. 目前,我正在制作解决数独的C ++程序。 In order to do this, I calculate the "energy" of the sudoku (the number of faults) frequently. 为此,我经常计算数独的“能量”(故障数)。 This calculation unfortunately takes up a lot of computation time. 不幸的是,该计算占用了大量的计算时间。 I think that it can be sped up significantly by using pointers and references in the calculation, but have trouble figuring out how to implement this. 我认为可以通过在计算中使用指针和引用来显着提高它的速度,但是很难弄清楚如何实现它。

In my solver class, I have a vector<vector<int> data-member called _sudoku , that contains the values of each site. 在我的求解器类中,我有一个名为_sudokuvector<vector<int>数据成员,其中包含每个站点的值。 Currently, when calculating the energy I call a lot of functions with pass-by-value. 当前,在计算能量时,我使用传递值调用了许多函数。 I tried adding a & in the arguments of the functions and a * when making the variables, but this did not work. 我尝试在创建变量时在函数的参数中添加&并在*中添加*,但这不起作用。 How can I make this program run faster by using pass-by-reference? 如何通过引用传递使该程序运行更快?

Calculating the energy should not change the vector anyway so that would be better. 计算能量无论如何都不应改变矢量,这样会更好。

I used the CPU usage to track down 80% of the calculation time to the function where vectors are called. 我使用CPU使用率来追踪80%的计算时间到调用向量的函数。

int SudokuSolver::calculateEnergy() {
    int energy = 243 - (rowUniques() + colUniques() + blockUniques());//count number as faults
    return energy;
}


int SudokuSolver::colUniques() {
    int count = 0;
    for (int col = 0; col < _dim; col++) {
        vector<int> colVec = _sudoku[col];
        for (int i = 1; i <= _dim; i++) {
            if (isUnique(colVec, i)) {
                count++;
            }
        }
    }
    return count;
}
int SudokuSolver::rowUniques() {
    int count = 0;
    for (int row = 0; row < _dim; row++) {

        vector<int> rowVec(_dim);
        for (int i = 0; i < _dim; i++) {
            rowVec[i] = _sudoku[i][row];
        }
        for (int i = 1; i <= _dim; i++) {
            if (isUnique(rowVec, i)) {
                count++;
            }
        }
    }
    return count;
}

int SudokuSolver::blockUniques() {
    int count = 0;
    for (int nBlock = 0; nBlock < _dim; nBlock++) {
        vector<int> blockVec = blockMaker(nBlock);
        for (int i = 1; i <= _dim; i++) {
            if (isUnique(blockVec, i)) {
                count++;
            }
        }
    }
    return count;
}

vector<int> SudokuSolver::blockMaker(int No) {
    vector<int> block(_dim);
    int xmin = 3 * (No % 3);
    int ymin = 3 * (No / 3);
    int col, row;
    for (int i = 0; i < _dim; i++) {
        col = xmin + (i % 3);
        row = ymin + (i / 3);
        block[i] = _sudoku[col][row];
    }
    return block;
}

bool SudokuSolver::isUnique(vector<int> v, int n) {
    int count = 0;
    for (int i = 0; i < _dim; i++) {
        if (v[i] == n) {
            count++;
        }
    }
    if (count == 1) {
        return true;
    } else {
        return false;
    }
}

The specific lines that use a lot of computatation time are the ones like: vector<int> colVec = _sudoku[col]; vector<int> colVec = _sudoku[col];大量计算时间的特定行如下: vector<int> colVec = _sudoku[col]; and every time isUnique() is called. 并且每次调用isUnique()

I expect that if I switch to using pass-by-reference, my code will speed up significantly. 我希望如果我切换到使用按引用传递,我的代码将大大加快速度。 Could anyone help me in doing so, if that would indeed be the case? 如果确实是这样的话,有人可以帮助我吗?

Thanks in advance. 提前致谢。

If you change your SudokuSolver::isUnique to take vector<int> &v , that is the only change you need to do pass-by-reference instead of pass-by-value. 如果将SudokuSolver::isUnique更改为vector<int> &v ,则这是唯一需要进行按引用传递而不是按值传递的更改。 Passing with a pointer will be similar to passing by reference, with the difference that pointers could be re-assigned, or be NULL, while references can not. 用指针传递将类似于通过引用传递,不同之处在于可以重新分配指针或将其设置为NULL,而不能通过引用传递指针。

I suspect you would see some performance increase if you are working on a sufficiently large-sized problem where you would be able to distinguish a large copy (if your problem is small, it will be difficult to see minor performance increases). 我怀疑如果您正在处理足够大的问题,并且能够区分较大的副本(如果问题很小,则很难看到次要的性能提高),您会看到性能提高。

Hope this helps! 希望这可以帮助!

vector<int> colVec = _sudoku[col]; does copy/transfer all the elements, while const vector<int>& colVec = _sudoku[col]; 复制/传输所有元素,而const vector<int>& colVec = _sudoku[col]; would not (it only creates an alias for the right hand side). 不会(它只会为右侧创建一个别名)。

Same with bool SudokuSolver::isUnique(vector<int> v, int n) { versus bool SudokuSolver::isUnique(const vector<int>& v, int n) { bool SudokuSolver::isUnique(vector<int> v, int n) {bool SudokuSolver::isUnique(const vector<int>& v, int n) {

Edited after Jesper Juhl's suggestion: The const addition makes sure that you don't change the reference contents by mistake. 根据Jesper Juhl的建议进行编辑: const加法确保您不会误更改参考内容。

Edit 2: Another thing to notice is that vector<int> rowVec(_dim); 编辑2:还要注意的另一件事是vector<int> rowVec(_dim); these vectors are continuously allocated and unallocated at each iteration, which might get costly. 这些向量会在每次迭代时连续分配和取消分配,这可能会增加成本。 You could try something like 您可以尝试类似

int SudokuSolver::rowUniques() {
    int count = 0;
    vector<int> rowVec(_maximumDim); // Specify maximum dimension       
    for (int row = 0; row < _dim; row++) {
        for (int i = 0; i < _dim; i++) {
            rowVec[i] = _sudoku[i][row];
        }
        for (int i = 1; i <= _dim; i++) {
            if (isUnique(rowVec, i)) {
                count++;
            }
        }
    }
    return count;
}

if that doesn't mess up with your implementation. 如果这不影响您的实施。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM