我試圖用OpenCL來並行處理經典的map-reduce問題(它可以與MPI很好地並行),即AMD實現。但結果困擾我。用opencl解決經典的map-reduce問題?
讓我簡短的有關該問題的第一位。有兩種類型的數據流入系統:特徵集(每個30個參數)和樣本集(每個9000個維度)。從某種意義上說,這是一個經典的地圖縮減問題,我需要計算每個樣本(地圖)上每個要素的得分。然後,總結每個功能的總體評分(Reduce)。有大約10k功能和30k樣本。
我嘗試不同的方法來解決這個問題。首先,我試圖通過功能分解問題。問題在於分數計算由隨機存儲器訪問組成(選擇9000多個維度中的一些並進行加/減計算)。由於我無法合併內存訪問,因此需要花費。然後,我嘗試用樣本分解問題。問題是總結總分,所有線索都爭奪少量分數變數。它一直覆蓋原來不正確的分數。 (我不能先進行個人得分,因爲它需要10k * 30k * 4字節)。
我嘗試的第一個方法,讓我有8個線程的i7上的CPU 860相同的性能。但是,我認爲這個問題不可解決:它與射線追蹤問題非常相似(爲此,您計算的是數百萬條射線對數百萬個三角形的計算)。有任何想法嗎?
另外,我張貼一些代碼,我有:
分解的功能(工程,但慢):
__kernel void __ccv_cl_pos_error_rate(__global unsigned int* err_rate,
__constant int* feature, __constant int* data, int num, __constant
unsigned int* w, int s, int isiz0, int isiz01, int step0, int step1)
{
int igrid = get_global_id(0);
__constant int* of = feature + igrid * 30;
unsigned int e = 0;
int k, i;
int step[] = { step0, step1 };
for (k = 0; k < num; k++)
{
__constant int* kd = data + k * isiz01;
int pmin = kd[of[0] * isiz0 + of[1] + of[2] * step[of[0]]];
int nmax = kd[of[3] * isiz0 + of[4] + of[5] * step[of[3]]];
for (i = 0; i < 5; i++)
{
if (of[i * 6] >= 0)
pmin = min(pmin, kd[of[i * 6] * isiz0 + of[i * 6 + 1] + of[i * 6 + 2] * step[of[i * 6]]]);
if (of[i * 6 + 3] >= 0)
nmax = max(nmax, kd[of[i * 6 + 3] * isiz0 + of[i * 6 + 4] + of[i * 6 + 5] * step[of[i * 6 + 3]]]);
}
if (pmin <= nmax)
e += w[s + k];
}
err_rate[igrid] += e;
}
分解的樣品,不工作:
__kernel void __ccv_cl_pos_error_rate(__global unsigned int* err_rate,
__constant int* feature, __constant int* data, int num, __constant
unsigned int* w, int s, int isiz0, int isiz01, int step0, int step1,
__local int* shared)
{
int igrid = get_global_id(0);
int lsize = get_local_size(0);
int lid = get_local_id(0);
unsigned int e = 0;
int k, i;
int ws = w[s + igrid];
int step[] = { step0, step1 };
for (k = 0; k < isiz01; k += lsize)
if (k + lid < isiz01)
shared[k + lid] = data[igrid * isiz01 + k + lid];
barrier(....);
for (k = 0; k < num; k++)
{
__constant int* of = feature + k * 30;
int pmin = shared[of[0] * isiz0 + of[1] + of[2] * step[of[0]]];
int nmax = shared[of[3] * isiz0 + of[4] + of[5] * step[of[3]]];
for (i = 0; i < 5; i++)
{
if (of[i * 6] >= 0)
pmin = min(pmin, shared[of[i * 6] * isiz0 + of[i * 6 + 1] + of[i * 6 + 2] * step[of[i * 6]]]);
if (of[i * 6 + 3] >= 0)
nmax = max(nmax, shared[of[i * 6 + 3] * isiz0 + of[i * 6 + 4] + of[i * 6 + 5] * step[of[i * 6 + 3]]]);
}
if (pmin <= nmax)
err_rate[k] += ws; // here is wrong.
}
barrier(....);
}
是的,沒關係,我的第二次嘗試是有缺陷的。從本質上講,我試圖將每個工作組的一個樣本加載到本地內存中並進行計算,但它只是搞砸了。我會嘗試清理它,獲得一些基準並重新發布。謝謝。 – liuliu 2010-04-01 15:01:54
也許這是類似於你正在嘗試做的事情(它比我嘗試過的任何事情都複雜得多): (1)對於工作組中的某些特徵子集的子集... (2)創建列表,將所有指數記錄在樣本中; (3)排序這些指標; (4)從樣本中加載數據(用值替換指數?); (5)使用局部樣本完成計算。 不幸的是,我認爲* *你的問題太稀疏了,爲了幫助(該功能不具有共同足夠的樣本本地內存的限制大小)。但我想我會形容它「以防萬一」... – 2010-04-01 15:55:25
ps如果它是稀疏的,並且如果所有數據都適合多核CPU的l3緩存,那麼這可能是您的甜蜜點,直到GPU具有相似大小的緩存... – 2010-04-01 15:57:41