OpenCL - 数组值被覆盖
OpenCL - Array values being overwritten
我遇到了一个问题,我以前的数组元素被新值覆盖了。
代码试图做什么
我最初有一个包含 100 个元素的数组(全部来自正弦函数,这是我的输入)。它本质上是充当 FIFO 缓冲区,并在新输入被推入 FIFO 时计算数组的平均值。我这样做的原因是因为我正在尝试实施移动平均过滤器。
但是,输出往往会覆盖以前的值。
例如,如果 FIFO 缓冲区的第一个元素为 1(目前这意味着缓冲区的其余部分中有 0),则位置 0 处的输出数组的值将为 0.01。下一次,如果下一个输入值为 0.9,则索引 1 处的输出值为 (0.01+0.009)。但是这是索引 0 的值也被覆盖为与索引 1 相同的值的地方。
我决定在 java 中编写相同的代码,它运行得非常好。如果有人能解决这个问题,我将不胜感激。
kernel void lowpass(__global float *Array, __global float *Output) {
float fifo[100];
int queueIn;
float tempVal;
queueIn = 0;
int idx = get_global_id(0);
Output[idx] = 0;
fifo[idx] = 0;
for(int i = queueIn; i < 3; i++){
fifo[i] = Array[i];
tempVal = (float)0;
for(int j = 0; j < 3; j++){
tempVal = (float) (fifo[j]*(.01) + tempVal);
}
Output[queueIn] = tempVal;
queueIn = queueIn + 1;
}
}
请注意,出于调试目的,我将 for 循环设置为 3。从跟踪代码来看,它不应该这样做。但话又说回来,我可能会遗漏一些小东西。
**此外,出于调试原因,我删除了很多变量,例如 queueIn,我只需要使数组不覆盖以前的值。
cmd 的示例输出
Java代码
public static void main(String[] args) {
// TODO Auto-generated method stub
//Input,output and fifo arrays
float [] fifo = new float[100];
float [] input = new float[100];
float [] output = new float[100];
//temporary value to hold computed result
float temp = 0;
//initialize array values to 0
for(int i =0;i<100;i++){
fifo[i] = 0;
input[i] = 0;
output[i] = 0;
}
//I know this produces a constant result, but its just
//proof of concept. this array will have values of .707 throughout it
for(int i =0;i<100;i++){
temp = (float) Math.sin(Math.toRadians(45));
input[i] = temp;
}
int queueIn;
float tempVal;
tempVal=0;
queueIn = 0;
//Insert one value at a time into the fifo buffer (first for loop)
for(int i = queueIn; i < 100; i++){
fifo[i] = input[i];
//reset to 0 so it can reaccumilate
tempVal = 0;
//accumilate the values in the array multiplied by a coefficient one value in
//the array changes every time the first for loop executes.
for(int j = 0; j < 100; j++){
tempVal = (float) (fifo[j]*(0.01) + tempVal);
}
//store the value in the current index of the output array.
output[queueIn] = tempVal;
queueIn = queueIn + 1;
}
//verify results
for(int i =0;i<100;i++){
System.out.println(output[i]);
}
}
你的内核的第一部分被实现为 运行 作为 NDRange 和主要部分当为任务完成计算时(运行 作为单个工作项)因此每个工作项正在覆盖值。
根据您的 Java 实现,NDRange 内核实现应该是这样的:
kernel void lowpass(__global float *Array, __global float *Output) {
int idx = get_global_id(0);
float tempVal = 0.0f;
for(int j = 0; j < idx+1; j++){
tempVal += Array[j] * 0.01f;
}
Output[idx] = tempVal;
}
我遇到了一个问题,我以前的数组元素被新值覆盖了。
代码试图做什么
我最初有一个包含 100 个元素的数组(全部来自正弦函数,这是我的输入)。它本质上是充当 FIFO 缓冲区,并在新输入被推入 FIFO 时计算数组的平均值。我这样做的原因是因为我正在尝试实施移动平均过滤器。
但是,输出往往会覆盖以前的值。 例如,如果 FIFO 缓冲区的第一个元素为 1(目前这意味着缓冲区的其余部分中有 0),则位置 0 处的输出数组的值将为 0.01。下一次,如果下一个输入值为 0.9,则索引 1 处的输出值为 (0.01+0.009)。但是这是索引 0 的值也被覆盖为与索引 1 相同的值的地方。
我决定在 java 中编写相同的代码,它运行得非常好。如果有人能解决这个问题,我将不胜感激。
kernel void lowpass(__global float *Array, __global float *Output) {
float fifo[100];
int queueIn;
float tempVal;
queueIn = 0;
int idx = get_global_id(0);
Output[idx] = 0;
fifo[idx] = 0;
for(int i = queueIn; i < 3; i++){
fifo[i] = Array[i];
tempVal = (float)0;
for(int j = 0; j < 3; j++){
tempVal = (float) (fifo[j]*(.01) + tempVal);
}
Output[queueIn] = tempVal;
queueIn = queueIn + 1;
}
}
请注意,出于调试目的,我将 for 循环设置为 3。从跟踪代码来看,它不应该这样做。但话又说回来,我可能会遗漏一些小东西。
**此外,出于调试原因,我删除了很多变量,例如 queueIn,我只需要使数组不覆盖以前的值。
cmd 的示例输出
Java代码
public static void main(String[] args) {
// TODO Auto-generated method stub
//Input,output and fifo arrays
float [] fifo = new float[100];
float [] input = new float[100];
float [] output = new float[100];
//temporary value to hold computed result
float temp = 0;
//initialize array values to 0
for(int i =0;i<100;i++){
fifo[i] = 0;
input[i] = 0;
output[i] = 0;
}
//I know this produces a constant result, but its just
//proof of concept. this array will have values of .707 throughout it
for(int i =0;i<100;i++){
temp = (float) Math.sin(Math.toRadians(45));
input[i] = temp;
}
int queueIn;
float tempVal;
tempVal=0;
queueIn = 0;
//Insert one value at a time into the fifo buffer (first for loop)
for(int i = queueIn; i < 100; i++){
fifo[i] = input[i];
//reset to 0 so it can reaccumilate
tempVal = 0;
//accumilate the values in the array multiplied by a coefficient one value in
//the array changes every time the first for loop executes.
for(int j = 0; j < 100; j++){
tempVal = (float) (fifo[j]*(0.01) + tempVal);
}
//store the value in the current index of the output array.
output[queueIn] = tempVal;
queueIn = queueIn + 1;
}
//verify results
for(int i =0;i<100;i++){
System.out.println(output[i]);
}
}
你的内核的第一部分被实现为 运行 作为 NDRange 和主要部分当为任务完成计算时(运行 作为单个工作项)因此每个工作项正在覆盖值。
根据您的 Java 实现,NDRange 内核实现应该是这样的:
kernel void lowpass(__global float *Array, __global float *Output) {
int idx = get_global_id(0);
float tempVal = 0.0f;
for(int j = 0; j < idx+1; j++){
tempVal += Array[j] * 0.01f;
}
Output[idx] = tempVal;
}