[英]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. 在我的求解器类中,我有一个名为_sudoku
的vector<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.