用opencl解决一个经典的MapReduce问题?

用opencl解决一个经典的MapReduce问题?,mapreduce,raytracing,opencl,Mapreduce,Raytracing,Opencl,我正在尝试将一个经典的map-reduce问题(可以很好地与MPI并行)与OpenCL并行,即AMD实现。但结果让我很烦恼 让我先简要介绍一下这个问题。有两种类型的数据流入系统:特征集(每个参数30个)和样本集(每个参数9000多个维度)。这是一个经典的map reduce问题,因为我需要计算每个样本(map)上每个特征的分数。然后,总结每个功能的总得分(减少)。大约有10k个特征和30k个样本 我尝试了不同的方法来解决这个问题。首先,我试图通过特征分解问题。问题在于分数计算由随机内存访问组成(

我正在尝试将一个经典的map-reduce问题(可以很好地与MPI并行)与OpenCL并行,即AMD实现。但结果让我很烦恼

让我先简要介绍一下这个问题。有两种类型的数据流入系统:特征集(每个参数30个)和样本集(每个参数9000多个维度)。这是一个经典的map reduce问题,因为我需要计算每个样本(map)上每个特征的分数。然后,总结每个功能的总得分(减少)。大约有10k个特征和30k个样本

我尝试了不同的方法来解决这个问题。首先,我试图通过特征分解问题。问题在于分数计算由随机内存访问组成(从9000+维度中选择一些维度并进行加减计算)。因为我不能合并内存访问,所以成本很高。然后,我尝试通过样本分解问题。问题是,为了汇总总分数,所有线程都在争夺少数分数变量。它不断覆盖原来不正确的分数。(由于需要10k*30k*4字节,我不能先进行单项评分,以后再进行汇总)

我尝试的第一种方法在I7860 CPU上提供了与8个线程相同的性能。然而,我并不认为这个问题是无法解决的:它与光线跟踪问题非常相似(在这个问题中,您执行了数百万条光线对数百万个三角形的计算)。有什么想法吗

此外,我还发布了我的一些代码:

按功能分解(工作正常,但速度较慢):

\uuuuuu内核无效\uuuuuu ccv\uCL\uPOS\uu错误率(\uuuu全局无符号整数*错误率,
__常量int*特征,_常量int*数据,int num,_常量
无符号整数*w、整数s、整数isiz0、整数isiz01、整数步长0、整数步长1)
{
int igrid=get_global_id(0);
__常数int*of=特征+igrid*30;
无符号整数e=0;
int k,i;
int step[]={step0,step1};
对于(k=0;k=0)
pmin=min(pmin,kd[i*6]*isiz0+i*6+1]+i*6+2]*step[i*6]];
如果(属于[i*6+3]>=0)
nmax=max(nmax,kd[i*6+3]*isiz0+i*6+4]+i*6+5]*阶跃[i*6+3]];
}
如果(pmin=0)
pmin=min(pmin,[i*6]*isiz0+的[i*6+1]+的[i*6+2]*步骤[i*6]];
如果(属于[i*6+3]>=0)
nmax=max(nmax,共享的[i*6+3]*isiz0+i*6+4]+i*6+5]*step[i*6+3]];
}

if(pminhn的andrew cooke。从您的第一次尝试中,我现在更好地理解了这个问题,并且看到根据特性选择样本是您的致命之处

按特征选择样本是完全随机的,还是可以利用其中的规律性(对特征进行排序,以便使用相同样本的特征一起处理)?这是显而易见的,因此我猜这是不可能的


不幸的是,我不理解你的第二次尝试。

是的,没关系,我的第二次尝试是有缺陷的。基本上,我试图将每个工作组的一个样本加载到本地内存并进行计算,但它只是搞砸了。我将尝试清理它,获取一些基准,然后再次发布。谢谢。也许这与你正在尝试的类似做(这比我尝试过的任何事情都要复杂得多):(1)对于工作组中某些大小的特征子集…(2)在本地内存中创建一个列表,将所有索引放入样本中;(3)对这些索引进行排序;(4)从样本中加载数据(用值替换索引?);(5)使用本地样本完成计算。不幸的是,我认为您的问题过于稀疏,无法提供帮助(功能没有足够的样本用于受限的本地内存)。但我认为我应该“以防万一”来描述它…ps如果它是如此稀疏,并且如果您的所有数据都适合多核CPU的l3缓存,那么在GPU具有类似大小的缓存之前,这可能是您的最佳选择…只是更新:功能分解没有起作用。性能受到影响,atom_add出现问题(猜测是因为_常量已经被缓存,将其显式缓存到本地并没有多大帮助)。但是,在第一次尝试的基础上进行了更多优化(在第一次尝试中,我没有在GPU内核中使用全CPU使用的优化技术进行功能比较),与8线程I7860 CPU版本(在HD5770GPU上)相比,我现在看到了75%的速度提升。仍然可以使用它。
__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(....);
}