Java使用数组的速度比C ++中std :: vector快8倍。我做错什么了?
这是C ++版本,其中每个节点的数据收集到一个结构中,并使用该结构的单个向量:
#include <vector>#include <cmath>#include <iostream>class Floodisolation {public: Floodisolation() : numberOfCells(20000), 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) {data[i].flagInterface[j] = !data[i].flagInterface[j];data[i].typeInterface[j] = data[i].typeInterface[j] + 1;data[i].neighborIds[j] = data[i].neighborIds[j] + 1; } } }private: const int numberOfCells; static const int nEdges = 6; struct data_t { bool floodedCells = 0; bool floodedCellsTimeInterval = 0; double valueOfCellIds = 0; double h = 0; double h0 = 0; double vU = 0; double vV = 0; double vUh = 0; double vVh = 0; double vUh0 = 0; double vVh0 = 0; double ghh = 0; double sfx = 0; double sfy = 0; double qInflow = 0; double qStartTime = 0; double qEndTime = 0; double qIn = 0; double nx = 0; double ny = 0; double floorLevels = 0; int lowerFloorCells = 0; bool floorCompleteleyFilled = 0; double cellLocationX = 0; double cellLocationY = 0; double cellLocationZ = 0; int levelOfCell = 0; bool flagInterface[nEdges] = {}; int typeInterface[nEdges] = {}; int neighborIds[nEdges] = {}; }; std::vector<data_t> data;};int main() { std::ios_base::sync_with_stdio(false); Floodisolation isolation; clock_t start = clock(); for (int i = 0; i < 400; ++i) { if(i % 100 == 0) { std::cout << i << 'n'; } isolation.isUpdateNeeded(); } clock_t stop = clock(); std::cout << 'Time: ' << difftime(stop, start) / 1000 << 'n';}
现场例子
现在的时间是Java版本速度的2倍。(846比1631)。
奇怪的是,JIT注意到缓存遍历整个地方访问数据的烧录,并将您的代码转换为逻辑上相似但效率更高的顺序。
我还关闭了stdio同步,这仅在将printf/ scanf与C std::cout和混合使用时才需要std::cin。碰巧的是,您只打印了一些值,但是C 的默认打印行为过于偏执且效率低下。
如果nEdges不是实际的常数值,则必须从中删除3个“数组”值struct。那不应该造成巨大的性能损失。
struct通过减小大小对值进行排序,从而减少内存占用量(并在无关紧要的情况下对访问进行排序),可能还可以提高性能。但是我不确定。
一条经验法则是,单个高速缓存未命中的开销比指令高100倍。安排数据具有缓存一致性具有很多价值。
如果struct无法将数据重新排列到中,则可以将迭代更改为依次遍历每个容器。
顺便说一句,请注意Java和C 版本在它们之间有一些细微的差异。我发现的一个问题是Java版本在“ for each edge”循环中有3个变量,而C只有2个变量。我使我的代码与Java匹配。不知道还有没有
解决方法我有以下带有几个大数组的Java代码,这些数组永远不会改变其大小。它在我的计算机上运行1100毫秒。
我在C ++中实现了相同的代码并使用std::vector。
在我的计算机上,运行完全相同的代码的C ++实现的时间为8800 ms。我做错了什么,所以运行缓慢?
基本上,代码执行以下操作:
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的不同数组。
您可以在以下链接下找到这两种实现:
Java:https://ideone.com/R8KqjTC ++:https://ideone.com/Lu7RpE(由于时间限制,在ideone上,我只能运行400次而不是2000次循环。但是即使在这里,也有3次相差)
相关文章:
1. javascript - 引入 simditor,但是显示标签,这个怎么解决。2. android - 目前有哪些用Vue.js开发移动App的方案?3. 为什么要通过常量的方式拐弯抹角的写呢,直接写DSN之类的不好吗4. python - 关于flask 静态文件配置404的问题5. python - scrapy获取网页指定内容,后翻到下一页继续,固定循环次数。。问题6. defined这个实验代码我这里不对哇7. python - 一个关于爬虫的问题8. linux - 为公司配置服务器,要求在上面装win7的虚拟机,那我还需要装桌面环境吗?9. javascript - 仿着echarts官网的地图做了个例子,但是只显示出来了地点,没有画出飞机动态效果??急10. android - 安卓实现类似QQ刚换聊天背景的功能