c ++数组访问程序无法扩展

时间:2016-08-11 09:13:44

标签: c++ multithreading parallel-processing

我有一小段代码可以执行以下操作:

  1. 按顺序访问struct(vec1)数组
  2. 根据从struct array
  3. 获取的值随机访问int数组(hashT)
  4. 使用从int数组中获取的值修改struct数组的值。
  5. 我在同一个numa节点上的8个物理cpus上运行程序。但是对于大小为5M的hashT(即其中有5M ints),我只获得了x7.2的加速。我改变了hashT的大小,看到当它很小时,我得到x7.9加速,但随着它变得越来越大并且在某些时候(当阵列中有3M整数时),加速开始下降。我有一个200GB的RAM,所以内存应该不是问题。我还测量了内存带宽,而且我还没有接近最大可用带宽的一半。所以我认为这可能是由于缓存的争用。我有一个20MB的三级缓存,由所有线程共享。但是我测量了L2和L3缓存缺失,我发现无论我使用多少线程它们几乎都是一样的(确实增加hashT的大小会导致更多的缓存未命中)。所以我没有看到加速下降的原因。任何人都可以给我一个想法吗?

    #include<iostream>
    #include<vector>
    #include<chrono>
    #include<omp.h>
    #include<stdio.h>
    using namespace std;
    
    typedef std::chrono::milliseconds ms;
    
    struct Element{
        int a, b, c;
        Element() : a(0), b(1), c(2) {}
        Element(int aa, int bb, int cc) : a(aa), b(bb), c(cc) {}
    };
    
    int main(int argc, char *argv[]){
        int HASHT_SIZE = atoi(argv[1]);
        int RID_SIZE = 5000000;
    
        auto start = std::chrono::high_resolution_clock::now();
        auto end = std::chrono::high_resolution_clock::now();
    
            vector<vector<Element> > vec1(40);
            for(size_t i = 0; i < vec1.size(); i++){
                vec1[i].reserve(RID_SIZE);
                for(size_t j = 0; j < vec1[i].capacity(); j++){
                    vec1[i].push_back(Element(rand() % HASHT_SIZE,0,0));
                }
            }
    
            //initialize hashT
            vector<int> hashT;
            hashT.reserve(HASHT_SIZE);
            for(int i = 0; i < HASHT_SIZE; i++){
                hashT.push_back(rand() % 2);
            }
    
            start = std::chrono::high_resolution_clock::now();
    
            //test program
            #pragma omp parallel for schedule(dynamic)
            for(int j = 0; j < 40; j++)
            { 
                for(size_t i = 0; i < RID_SIZE; i++){
                    int nid = hashT[vec1[j][i].a];
                    for(int k = 0; k < 10; k++){
                        vec1[j][i].b += nid / (k+1);
                        vec1[j][i].c += nid / (k+1);
                    }
                }
            }
    
            end = std::chrono::high_resolution_clock::now();
    
            for(int i = 0; i < 40; i++){
                        for(int j = 0; j < 10; j++){
                                cout << vec1[i][j].a << vec1[i][j].b << vec1[i][j].c;
                        }
                }cout << endl;
    
        cout << "Time used: " << std::chrono::duration_cast<ms>(end - start).count() << endl;
    
        return 0;
    }
    

0 个答案:

没有答案