Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何构造这个OpenCL暴力代码_Python_Algorithm_Opencl_Brute Force - Fatal编程技术网

Python 如何构造这个OpenCL暴力代码

Python 如何构造这个OpenCL暴力代码,python,algorithm,opencl,brute-force,Python,Algorithm,Opencl,Brute Force,我刚刚开始使用OpenCL,我一直在研究如何以一种合理有效的方式构造程序(主要是避免大量数据从GPU传输到GPU或任何正在进行工作的地方) 我想做的是,考虑到: v = r*i + b*j + g*k …我知道r、g和b的各种值的v,但是I、j和k是未知的。我想通过蛮力计算I/j/k的合理值 换句话说,我有一堆“原始”RGB像素值,我有这些颜色的去饱和版本。我不知道用于计算去饱和值的权重(I/j/k) 我最初的计划是: 将数据加载到CL缓冲区(以便输入r/g/b值和输出) 有一个内核,它接受

我刚刚开始使用OpenCL,我一直在研究如何以一种合理有效的方式构造程序(主要是避免大量数据从GPU传输到GPU或任何正在进行工作的地方)

我想做的是,考虑到:

v = r*i + b*j + g*k
…我知道
r
g
b
的各种值的
v
,但是
I
j
k
是未知的。我想通过蛮力计算
I
/
j
/
k
的合理值

换句话说,我有一堆“原始”RGB像素值,我有这些颜色的去饱和版本。我不知道用于计算去饱和值的权重(I/j/k)

我最初的计划是:

  • 将数据加载到CL缓冲区(以便输入r/g/b值和输出)

  • 有一个内核,它接受三个可能的矩阵值和各种像素数据缓冲区

    然后执行
    v=r*i+b*j+g*k
    ,将
    v
    的值减去已知值,并将其存储在“分数”缓冲区中

  • 另一个内核计算该值的RMS误差(如果所有输入值的差值为零,则i/j/k的值为“正确”)

  • 我已经完成了这项工作(使用Python和PyCL编写),但我想知道如何进一步并行这项工作(通过一次尝试多个I/j/k值)

    我的问题是,我有4个只读缓冲区(3个用于输入值,1个用于预期值),但我需要一个单独的“分数”缓冲区用于每个I/j/k组合

    另一个问题是RMS计算是最慢的部分,因为它实际上是单线程的(将“score”中的所有值相加,并将sqrt()相加)

    基本上,我想知道是否有一个合理的方法来构建这样一个程序

    这似乎是一项非常适合OpenCL的任务——希望对我目标的描述不会太复杂!如前所述,为了更清楚起见,这是我尝试做的Python版本:

    import sys
    import math
    import random
    
    
    def make_test_data(w = 128, h = 128):
        in_r, in_g, in_b = [], [], []
    
        print "Make raw data"
        for x in range(w):
            for y in range(h):
                in_r.append(random.random())
                in_g.append(random.random())
                in_b.append(random.random())
    
        # the unknown values
        mtx = [random.random(), random.random(), random.random()]
    
        print "Secret numbers were: %s" % mtx
    
        out_r = [(r*mtx[0] + g*mtx[1] + b*mtx[2]) for (r, g, b) in zip(in_r, in_g, in_b)]
    
        return {'in_r': in_r, 'in_g': in_g, 'in_b': in_b,
                'expected_r': out_r}
    
    
    def score_matrix(ir, ig, ib, expected_r, mtx):
        ms = 0
        for i in range(len(ir)):
            val = ir[i] * mtx[0] + ig[i] * mtx[1] + ib[i] * mtx[2]
            ms += abs(val - expected_r[i]) ** 2
        rms = math.sqrt(ms / float(len(ir)))
        return rms
    
    
    # Make random test data
    test_data = make_test_data(16, 16)
    
    
    lowest_rms = sys.maxint
    closest = []
    
    divisions = 10
    for possible_r in range(divisions):
        for possible_g in range(divisions):
            for possible_b in range(divisions):
    
                pr, pg, pb = [x / float(divisions-1) for x in (possible_r, possible_g, possible_b)]
    
                rms = score_matrix(
                    test_data['in_r'], test_data['in_g'], test_data['in_b'], 
                    test_data['expected_r'],
                    mtx = [pr, pg, pb])
    
                if rms < lowest_rms:
                    closest = [pr, pg, pb]
                    lowest_rms = rms
    
    print closest
    
    导入系统 输入数学 随机输入 def制造测试数据(w=128,h=128): in_r,in_g,in_b=[],[],[] 打印“生成原始数据” 对于范围(w)内的x: 对于范围(h)内的y: in\u r.append(random.random()) in_g.append(random.random()) in_b.append(random.random()) #未知值 mtx=[random.random(),random.random(),random.random()] 打印“机密号码为:%s”%mtx out_r=[(r*mtx[0]+g*mtx[1]+b*mtx[2]),用于(r,g,b)压缩(in_r,in_g,in_b)] 返回{'in_r':in_r,'in_g':in_g,'in_b':in_b, 'expected\u r':out\u r} def分数矩阵(ir、ig、ib、预期值、mtx): ms=0 对于范围内的i(len(ir)): val=ir[i]*mtx[0]+ig[i]*mtx[1]+ib[i]*mtx[2] ms+=abs(val-预期值[i])**2 rms=数学sqrt(ms/float(len(ir))) 返回rms #随机抽取测试数据 测试数据=制作测试数据(16,16) 最低有效值=sys.maxint 最近的=[] 分区=10 对于可能的范围内(分区): 对于可能的范围内(分区): 对于范围内可能的_b(分区): pr,pg,pb=[x/float(divisions-1)表示x英寸(可能的、可能的、可能的)] rms=得分矩阵( 测试数据['in_r']、测试数据['in_g']、测试数据['in_b'], 测试数据['expected_r'], mtx=[pr、pg、pb]) 如果rms<最低值_rms: 最近的=[pr,pg,pb] 最低有效值=有效值 打印最近的
    i、j、k集是独立的吗?我想是的。很少有事情会影响你的表现:


  • 运行太多的小内核
  • 使用全局内存在分数矩阵和rm到rm之间进行通信
  • 您可以通过以下更改将两个内核重写为一个:

  • 让一个OpenCL工作组在不同的i,j,k上工作-你可以在CPU上预先生成这个
  • 为了执行1,您需要用一个线程处理数组的多个元素,您可以这样做:

    int i = get_thread_id(0);
    float my_sum = 0;
    
    for (; i < array_size; i += get_local_size(0)){
        float val = in_r[i] * mtx_r + in_g[i] * mtx_g + in_b[i] * mtx_b;
        my_sum += pow(fabs(expect_r[i] - val), 2);
    }
    
    inti=get\u thread\u id(0);
    浮动我的总和=0;
    对于(;i
  • 在此之后,将每个线程的my_sum写入本地内存,并使用reduce(O(log(n))算法求和)

  • 将结果保存到全局内存中


  • 或者,如果您需要按顺序计算i、j、k,您可以在OpenCL规范中查找barrier和memory fence函数,这样您就可以使用它们而不是运行两个内核,只需记住在第一步中总结所有内容,写入全局同步所有线程,然后再次总结

    有两个潜在问题:

  • 如果处理每个映像所需的工作量很小,那么内核启动开销可能会很大。这是通过在单个内核中组合对多个
    i、j、k
    值的求值来解决的问题
  • RMSE总和计算的序列化。这可能是目前更大的问题
  • 要解决(2),请注意求和可以并行计算,但它不像在输入中的每个像素上分别映射函数那样简单。这是因为求和需要在相邻元素之间传递值,而不是单独处理所有元素。这种模式通常被称为减少

    PyOpenCL包括对的高级支持。这里需要的是求和减少:
    pyopencl.array.sum(array)


    进一步了解这是如何在原始OpenCL中实现的,苹果的OpenCL文档包括一个并行的sum缩减。与您想做的事情最相关的部分是。

    “运行太多小内核”的
    main
    create\u reduction\u pass\u counts
    函数