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. docker gitlab 如何git clone?2. 關于docker下的nginx壓力測試3. angular.js - angularjs的自定義過濾器如何給文字加顏色?4. docker不顯示端口映射呢?5. nignx - docker內nginx 80端口被占用6. javascript - windows下如何使用babel,遇到了困惑7. dockerfile - [docker build image失敗- npm install]8. debian - docker依賴的aufs-tools源碼哪里可以找到啊?9. 老師您的微信號是多少?10. 在windows下安裝docker Toolbox 啟動Docker Quickstart Terminal 失敗!
