3 回答

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超6個(gè)贊
我創(chuàng)建了一種改進(jìn)的方法,稱為process_data_v3
#define ROUND_DOWN(x, s) ((x) & ~((s)-1))
void proccess_data_v2(float *data, int *hist, const int n, const int nbins, float max) {
int* hista;
#pragma omp parallel
{
const int nthreads = omp_get_num_threads();
const int ithread = omp_get_thread_num();
int lda = ROUND_DOWN(nbins+1023, 1024); //1024 ints = 4096 bytes -> round to a multiple of page size
#pragma omp single
hista = (int*)_mm_malloc(lda*sizeof(int)*nthreads, 4096); //align memory to page size
for(int i=0; i<nbins; i++) hista[lda*ithread+i] = 0;
#pragma omp for
for(int i=0; i<n; i++) {
float x = reconstruct_data(data[i]);
fill_hist(&hista[lda*ithread], nbins, max, x);
}
#pragma omp for
for(int i=0; i<nbins; i++) {
for(int t=0; t<nthreads; t++) {
hist[i] += hista[lda*t + i];
}
}
}
_mm_free(hista);
}

TA貢獻(xiàn)1859條經(jīng)驗(yàn) 獲得超6個(gè)贊
您可以在并行區(qū)域內(nèi)分配大數(shù)組,您可以在其中查詢所使用的實(shí)際線程數(shù):
int *hista;
#pragma omp parallel
{
const int nthreads = omp_get_num_threads();
const int ithread = omp_get_thread_num();
#pragma omp single
hista = new int[nbins*nthreads];
...
}
delete[] hista;
為了獲得更好的性能,我建議您將每個(gè)線程的塊的大小四舍五入為hista系統(tǒng)內(nèi)存頁面大小的倍數(shù),即使這可能在不同的部分直方圖之間留下空白。這樣,您既可以防止在NUMA系統(tǒng)上進(jìn)行錯(cuò)誤共享,又可以防止對(duì)遠(yuǎn)程內(nèi)存的訪問(但不能在最后的還原階段)。

TA貢獻(xiàn)1765條經(jīng)驗(yàn) 獲得超5個(gè)贊
這實(shí)際上取決于所使用的內(nèi)存管理器。例如,在某些發(fā)行版中,glibc配置為使用每個(gè)線程的競技場,并且每個(gè)線程都有自己的堆空間。較大的分配通常實(shí)現(xiàn)為匿名mmap
,因此總是獲得新的頁面。但是,哪個(gè)線程分配了內(nèi)存并不重要。哪個(gè)胎面首先接觸每個(gè)特定頁面很重要-Linux上當(dāng)前的NUMA策略是“首次接觸”,即物理內(nèi)存頁面來自NUMA節(jié)點(diǎn),在該節(jié)點(diǎn)中,第一次接觸該頁面的代碼在此運(yùn)行。
- 3 回答
- 0 關(guān)注
- 862 瀏覽
添加回答
舉報(bào)