我刚刚开始使用 OpenCL,我一直坚持如何以合理有效的方式构建程序(主要是避免大量数据与 GPU 之间的传输或任何正在完成的工作)
我想做的是,鉴于:
v = r*i + b*j + g*k
..我知道,和, 但是,和v
的各种值是未知的。我想通过蛮力计算//的合理值r
g
b
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