gpt4 book ai didi

Java 使用数组比 C++ 中的 std::vector 快 8 倍。我做错了什么?

转载 作者:IT老高 更新时间:2023-10-28 11:59:05 27 4
gpt4 key购买 nike

我有以下 Java 代码,其中包含几个永远不会改变大小的大数组。它在我的电脑上运行时间为 1100 毫秒。

我在 C++ 中实现了相同的代码并使用了 std::vector

在我的计算机上运行完全相同的代码的 C++ 实现的时间是 8800 毫秒。我做错了什么,导致它运行得这么慢?

代码基本上做了以下事情:

for (int i = 0; i < numberOfCells; ++i) {
h[i] = h[i] + 1;
floodedCells[i] = !floodedCells[i];
floodedCellsTimeInterval[i] = !floodedCellsTimeInterval[i];
qInflow[i] = qInflow[i] + 1;
}

它遍历大小约为 20000 的不同数组。

您可以在以下链接下找到这两种实现:

(在ideone上,由于时间限制,我只能运行循环400次而不是2000次。但即使在这里也有3次的差异)

最佳答案

是的,c++ 版本中的缓存需要锤击。似乎 JIT 能够更好地处理这个问题。

如果您将 isUpdateNeeded() 中的外部 for 更改为更短的片段。差异消失了。

下面的示例产生了 4 倍的加速。

void isUpdateNeeded() {
for (int i = 0; i < numberOfCells; ++i) {
h[i] = h[i] + 1;
floodedCells[i] = !floodedCells[i];
floodedCellsTimeInterval[i] = !floodedCellsTimeInterval[i];
qInflow[i] = qInflow[i] + 1;
qStartTime[i] = qStartTime[i] + 1;
qEndTime[i] = qEndTime[i] + 1;
}

for (int i = 0; i < numberOfCells; ++i) {
lowerFloorCells[i] = lowerFloorCells[i] + 1;
cellLocationX[i] = cellLocationX[i] + 1;
cellLocationY[i] = cellLocationY[i] + 1;
cellLocationZ[i] = cellLocationZ[i] + 1;
levelOfCell[i] = levelOfCell[i] + 1;
valueOfCellIds[i] = valueOfCellIds[i] + 1;
h0[i] = h0[i] + 1;
vU[i] = vU[i] + 1;
vV[i] = vV[i] + 1;
vUh[i] = vUh[i] + 1;
vVh[i] = vVh[i] + 1;
}
for (int i = 0; i < numberOfCells; ++i) {
vUh0[i] = vUh0[i] + 1;
vVh0[i] = vVh0[i] + 1;
ghh[i] = ghh[i] + 1;
sfx[i] = sfx[i] + 1;
sfy[i] = sfy[i] + 1;
qIn[i] = qIn[i] + 1;
for(int j = 0; j < nEdges; ++j) {
neighborIds[i * nEdges + j] = neighborIds[i * nEdges + j] + 1;
}
for(int j = 0; j < nEdges; ++j) {
typeInterface[i * nEdges + j] = typeInterface[i * nEdges + j] + 1;
}
}

}

这在一定程度上表明缓存未命中是速度下降的原因。同样重要的是要注意变量不相关,因此很容易创建线程解决方案。

订单已恢复

根据 stefans 的评论,我尝试使用原始大小将它们分组到一个结构中。这以类似的方式消除了即时缓存压力。结果是c++(CCFLAG -O3)版本比java版本快15%左右。

Varning 既不短也不漂亮。

#include <vector>
#include <cmath>
#include <iostream>



class FloodIsolation {
struct item{
char floodedCells;
char floodedCellsTimeInterval;
double valueOfCellIds;
double h;
double h0;
double vU;
double vV;
double vUh;
double vVh;
double vUh0;
double vVh0;
double sfx;
double sfy;
double qInflow;
double qStartTime;
double qEndTime;
double qIn;
double nx;
double ny;
double ghh;
double floorLevels;
int lowerFloorCells;
char flagInterface;
char floorCompletelyFilled;
double cellLocationX;
double cellLocationY;
double cellLocationZ;
int levelOfCell;
};
struct inner_item{
int typeInterface;
int neighborIds;
};

std::vector<inner_item> inner_data;
std::vector<item> data;

public:
FloodIsolation() :
numberOfCells(20000), inner_data(numberOfCells * nEdges), data(numberOfCells)
{

}
~FloodIsolation(){
}

void isUpdateNeeded() {
for (int i = 0; i < numberOfCells; ++i) {
data[i].h = data[i].h + 1;
data[i].floodedCells = !data[i].floodedCells;
data[i].floodedCellsTimeInterval = !data[i].floodedCellsTimeInterval;
data[i].qInflow = data[i].qInflow + 1;
data[i].qStartTime = data[i].qStartTime + 1;
data[i].qEndTime = data[i].qEndTime + 1;
data[i].lowerFloorCells = data[i].lowerFloorCells + 1;
data[i].cellLocationX = data[i].cellLocationX + 1;
data[i].cellLocationY = data[i].cellLocationY + 1;
data[i].cellLocationZ = data[i].cellLocationZ + 1;
data[i].levelOfCell = data[i].levelOfCell + 1;
data[i].valueOfCellIds = data[i].valueOfCellIds + 1;
data[i].h0 = data[i].h0 + 1;
data[i].vU = data[i].vU + 1;
data[i].vV = data[i].vV + 1;
data[i].vUh = data[i].vUh + 1;
data[i].vVh = data[i].vVh + 1;
data[i].vUh0 = data[i].vUh0 + 1;
data[i].vVh0 = data[i].vVh0 + 1;
data[i].ghh = data[i].ghh + 1;
data[i].sfx = data[i].sfx + 1;
data[i].sfy = data[i].sfy + 1;
data[i].qIn = data[i].qIn + 1;
for(int j = 0; j < nEdges; ++j) {
inner_data[i * nEdges + j].neighborIds = inner_data[i * nEdges + j].neighborIds + 1;
inner_data[i * nEdges + j].typeInterface = inner_data[i * nEdges + j].typeInterface + 1;
}
}

}

static const int nEdges;
private:

const int numberOfCells;

};

const int FloodIsolation::nEdges = 6;

int main() {
FloodIsolation isolation;
clock_t start = clock();
for (int i = 0; i < 4400; ++i) {
if(i % 100 == 0) {
std::cout << i << "\n";
}
isolation.isUpdateNeeded();
}

clock_t stop = clock();
std::cout << "Time: " << difftime(stop, start) / 1000 << "\n";
}

我的结果与 Jerry Coffins 的原始尺寸略有不同。对我来说,差异仍然存在。这很可能是我的 java 版本,1.7.0_75。

关于Java 使用数组比 C++ 中的 std::vector 快 8 倍。我做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29656648/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com