如何使用CUDA推力用下一个非缺失值填充数组中缺失的值?

如何使用CUDA推力用下一个非缺失值填充数组中缺失的值?,cuda,gpgpu,thrust,Cuda,Gpgpu,Thrust,通过使用带有max运算符的CUDA推力,我能够用以前的非缺失值(即左侧最后一个非缺失值)填充缺失值 但如何使用下一个非缺失值(右侧)进行填充?因此,例如,使用0作为缺少的值标记: Input: [0 1 0 0 4 0 6 0] Fill missing from left: [0 1 1 1 4 4 6 6] Fill missing from right: [0 1 4 4 4 6 6 6] <- want 输入:[0 1 0 4 0 6 0

通过使用带有
max
运算符的CUDA推力,我能够用以前的非缺失值(即左侧最后一个非缺失值)填充缺失值

但如何使用下一个非缺失值(右侧)进行填充?因此,例如,使用
0
作为缺少的值标记:

                  Input: [0 1 0 0 4 0 6 0]
 Fill missing from left: [0 1 1 1 4 4 6 6]
Fill missing from right: [0 1 4 4 4 6 6 6]   <- want
输入:[0 1 0 4 0 6 0]
左侧缺少填充:[0 1 1 4 6]
从右开始填充缺失:[0 1 4 4 6 6]从左到右扫描时,
max()
对升序值起作用的原因是当前最大值始终高于
0
缺失元素,因此它成为填充缺失元素的正确值,即使它有“内存”从一开始就一路走来

如果您只是从右向左扫描,
max()
不再工作,因为您有一个递减范围

因此,您似乎需要使用
rbegin()
rend()
从右向左扫描,此外,还需要使用MAX\u INT作为占位符,使用
min()
作为运算符

Input: [MAX_INT 1 MAX_INT MAX_INT 4 MAX_INT 6 MAX_INT]
Fill missing from right: [1 1 4 4 4 6 6 MAX_INT]
然后,您需要在左侧和右侧为您的特殊情况捏造一些东西。

从左到右扫描时,
max()
对升序值起作用的原因是当前最大值将始终高于
0
缺少的元素,因此,它成为填充缺失元素的正确值,即使它从一开始就有一个“内存”

如果您只是从右向左扫描,
max()
不再工作,因为您有一个递减范围

因此,您似乎需要使用
rbegin()
rend()
从右向左扫描,此外,还需要使用MAX\u INT作为占位符,使用
min()
作为运算符

Input: [MAX_INT 1 MAX_INT MAX_INT 4 MAX_INT 6 MAX_INT]
Fill missing from right: [1 1 4 4 4 6 6 MAX_INT]

然后,你需要在左边和右边为你的特殊情况捏造一些东西。

函子
FillMissing
意味着如果元素为0,用上一个元素替换它,否则保留它。使用反向迭代器时,“previous”表示正确的迭代器

#include <thrust/device_vector.h>
#include <thrust/scan.h>
#include <iterator>

template<class T>
struct FillMissing
{
    __host__ __device__ T operator()(const T& res, const T& dat)
    {
        return dat == T(0) ? res : dat;
    }
};

int main()
{
    thrust::device_vector<double> vec(8);
    vec[1] = 1;
    vec[4] = 4;
    vec[6] = 6;

    thrust::inclusive_scan(
            vec.rbegin(), vec.rend(),
            vec.rbegin(),
            FillMissing<double>());

    thrust::copy(
            vec.begin(), vec.end(),
            std::ostream_iterator<double>(std::cout, " "));
    std::cout << std::endl;
}

您可能需要额外的代码来处理尾随的0

functor
FillMissing
表示如果元素为0,则将其替换为上一个元素,否则保留它。使用反向迭代器时,“previous”表示正确的迭代器

#include <thrust/device_vector.h>
#include <thrust/scan.h>
#include <iterator>

template<class T>
struct FillMissing
{
    __host__ __device__ T operator()(const T& res, const T& dat)
    {
        return dat == T(0) ? res : dat;
    }
};

int main()
{
    thrust::device_vector<double> vec(8);
    vec[1] = 1;
    vec[4] = 4;
    vec[6] = 6;

    thrust::inclusive_scan(
            vec.rbegin(), vec.rend(),
            vec.rbegin(),
            FillMissing<double>());

    thrust::copy(
            vec.begin(), vec.end(),
            std::ostream_iterator<double>(std::cout, " "));
    std::cout << std::endl;
}


如果反转数组,您可能需要额外的代码来处理尾随的0

?当然,@ks6g10,但我看不出反转数组如何帮助解决上述问题。以相反的方式进行包含式扫描会使
[06666]
max
[00000000]
min
成为操作员,而不是需要的
[0144466]
。请你澄清一下你的解决方案好吗?非常感谢,“前瞻性”到底是什么意思?(我不知道如何阅读你的O/关系语法)。@MiloChen啊,好的,谢谢你的澄清。@RogerDahl,为你的混淆道歉。我只是想用它后面(右边)的数字填充
[0 1 0 0 4 0 6 0]
中的0,或者如果它是数组中最右边的元素,则使用它前面(左边)的元素填充。非常感谢。如果你反转数组?当然可以,@ks6g10,但我不认为反转数组有助于解决上述问题。以相反的方式进行包含式扫描会使
[06666]
max
[00000000]
min
成为操作员,而不是需要的
[0144466]
。请你澄清一下你的解决方案好吗?非常感谢,“前瞻性”到底是什么意思?(我不知道如何阅读你的O/关系语法)。@MiloChen啊,好的,谢谢你的澄清。@RogerDahl,为你的混淆道歉。我只是想用它后面(右边)的数字填充
[0 1 0 0 4 0 6 0]
中的0,或者如果它是数组中最右边的元素,则使用它前面(左边)的元素填充。非常感谢。我用米洛提供的数据测试了代码。如果只有一个尾随的零,它就可以工作。让我澄清一下,如果尾随的零超过一个,它就会失败。@Pavan我认为他的数据的结果将是
11444660
是的,你是对的。我用错误的方式测试它。不管怎样,你能编辑你的答案并说后面的零需要特殊的代码吗?我用米洛提供的数据测试了代码。如果只有一个尾随的零,它就可以工作。让我澄清一下,如果尾随的零超过一个,它就会失败。@Pavan我认为他的数据的结果将是
11444660
是的,你是对的。我用错误的方式测试它。无论如何,你能编辑你的答案并说尾随的零需要特殊的代码吗?这是可行的,但你能改成
asch::minimum()
而不是
min
,只是为了弄清楚。还提到您正在使用包含式扫描。这是可行的,但您是否可以更改为
推力::最小值()
,而不是
min
,只是为了清楚起见。并且还提到您正在使用包容性扫描。