简体   繁体   English

OpenCL-数组值被覆盖

[英]OpenCL - Array values being overwritten

I've encountered a problem where my previous array elements get overwritten with the new values. 我遇到了一个问题,其中以前的数组元素被新值覆盖。

What the code is attempting to do 代码正在尝试做什么

I originally had an array with 100 elements (all from a sine function, this was my input). 我最初有一个包含100个元素的数组(全部来自正弦函数,这是我的输入)。 It is essentially to act as a FIFO buffer and computer the average of the array as new inputs is pushed into the FIFO. 它本质上是充当FIFO缓冲区,并在将新输入推入FIFO时计算阵列的平均值。 The reason I am doing this is because I am trying to implement a moving average filter. 我这样做的原因是因为我正在尝试实现移动平均滤波器。

However, what happens is the output tends to overwrite the previous values. 但是,发生的是输出趋向于覆盖先前的值。 For example, if the first element of the FIFO buffer was 1 (that would currently mean that the rest of the buffer has 0 in it), the output array at position 0 would have 0.01 as the value. 例如,如果FIFO缓冲区的第一个元素为1(当前表示缓冲区的其余部分为0),则位置0处的输出数组的值为0.01。 The next time around, if the next input value was 0.9, the output value at index 1 would have (0.01+0.009). 下次,如果下一个输入值为0.9,则索引1的输出值将为(0.01 + 0.009)。 BUT this is where the value of index 0 also gets overwritten to the same value as index 1. 但是,这也是索引0的值也被覆盖为与索引1相同的值的地方。

I decided to write the same code in java and it works perfectly fine. 我决定用Java编写相同的代码,并且效果很好。 If anyone can figure out the issue I would really appreciate it. 如果有人能找出问题,我将不胜感激。

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; 
    }
}

Note I have the for loops set to 3 for debugging purposes. 注意我出于调试目的将for循环设置为3。 From tracing the code, it should not be doing this. 从跟踪代码开始,就不应该这样做。 But then again, I could be missing something small. 但是话又说回来,我可能会遗漏一些小东西。

**ALSO i have removed alot of the variables such as queueIn for debugging reasons, I just need to make the array not overwrite previous values. **此外,出于调试原因,我还删除了诸如queueIn之类的许多变量,我只需要使数组不覆盖以前的值即可。

Example output from cmd cmd的示例输出

在此处输入图片说明

Java code 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]);
    }

}

The first part of your kernel is implemented for being run as NDRange and the main part when the calculations are done for Task (to be run as single work item) therefore each work item is overwriting the values. 内核的第一部分实现为以NDRange的身份运行,而主体部分则是在完成Task(作为单个工作项运行)的计算时执行的,因此每个工作项都将覆盖值。

Based on your Java implementation the NDRange kernel implementation should be something like this: 根据您的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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM