• 分享一个 thrust 中的删除操作


    分享一个 thrust 中的删除操作

    工作需要,目前已知数据有400w,最终数据大小只有几w,如何将400w数据根据条件快速删除至w级别
    参考:
    copy_if()
    remove_copy_if()
    remove_if()

    remove_if()

    函数原型[2]

    ForwardIterator thrust::remove_if(ForwardIterator first, ForwardIterator last, Predicate pred)	
    

    解释:remove_if 从[first, last) 范围内删除每一个使谓词 pred(x) 为真的元素,remove_if 是稳定的,意味着被删除的元素的相对顺序是不变的。值得注意的是: remove_if不会破坏任何迭代器,不会改变迭代器范围。返回的迭代器是元素被移除后指向结果范围的末尾,此迭代器到末尾之间的元素将会是无意义的。
    如果想真正删除,可以使用

    S.erase(remove_if(S.begin(), S.end(), pred), S.end()))
    
    
    #include "cuda_runtime.h"
    #include "device_launch_parameters.h"
    #include <thrust/remove.h>
    #include <stdio.h>
    #include <thrust/device_vector.h>
    
    #define BLOCKSIZE 256
    
    extern "C" {
    	class tmpvec3 {
    	public:
    		float x, y, z;
    		__host__ __device__
    		tmpvec3() :x(0.0), y(0.0), z(0.0) {}
    		__host__ __device__
    		tmpvec3(float tx, float ty, float tz) : x(tx), y(ty), z(tz) {}
    	};
    }
    
    struct is_empty_point
    {
    	__host__ __device__
    		bool operator()(const tmpvec3 p)
    	{
    		return (p.x == 0 && p.y == 0 && p.z == 0);
    	}
    };
    
    __global__ void changeValue(tmpvec3* vertices, int start, int end, float val)
    {
    	int index = blockIdx.x * blockDim.x + threadIdx.x;
    	int stride = blockDim.x * gridDim.x;
    	for (int tIndex = index; tIndex < end && tIndex >= start; tIndex += stride)
    	{
    		vertices[tIndex].x = val;
    		vertices[tIndex].y = val;
    		vertices[tIndex].z = val;
    	}
    }
    
    int main()
    {
    	const int N = 6;
    	thrust::device_vector<tmpvec3> test_data(4000000);
    	tmpvec3* raw_ptr_data = thrust::raw_pointer_cast(&test_data[0]);
    	int start = 40000, end = 50000;
    	changeValue << <(end + BLOCKSIZE - 1) / BLOCKSIZE, BLOCKSIZE >> > (raw_ptr_data, start, end, 1.0);
    	printf("before erase data size : %d 
    ", test_data.size());
    	test_data.erase(thrust::remove_if(test_data.begin(), test_data.end(), is_empty_point()), test_data.end());
    	printf("data size : %d
    ", test_data.size());
    	system("pause");
    	return 0;
    }
    

    结果

    remove_copy_if()

    函数原型[2]

    __host__ __device__ 
    OutputIterator thrust::remove_copy_if(const thrust::detail::execution_policy_base<DerivedPolicy>& exec,
    InputIterator first,
    InputIterator last,
    OutputIterator result,
    Predicate pred 
    )	
    

    解释:remove_copy_if 将 [first, last) 范围内中,除了谓词为 true 的元素复制到结果中,这个操作是稳定的,也就是说顺序不会改变。

    // 和上一个例子相比仅改变了 main 函数
    int main()
    {
    	const int N = 6;
    	thrust::device_vector<tmpvec3> test_data(4000000);
    	thrust::host_vector<tmpvec3> h_test_data(4000000);
    	thrust::device_vector<tmpvec3> res_data(10000);
    	thrust::host_vector<tmpvec3> h_res_data(10000);
    
    	tmpvec3* raw_ptr_data = thrust::raw_pointer_cast(&test_data[0]);
    	
    	int start = 40000, end = 50000;
    	changeValue << <(end + BLOCKSIZE - 1) / BLOCKSIZE, BLOCKSIZE >> > (raw_ptr_data, start, end, 1.0);
    	thrust::copy(test_data.begin(), test_data.end(), h_test_data.begin());
    	printf("before erase data size : %d  first data x: %f, y: %f, z: %f 
    ", test_data.size(), h_test_data[0].x, h_test_data[0].y, h_test_data[0].z);
    	thrust::remove_copy_if(test_data.begin(), test_data.end(), res_data.begin(), is_empty_point());
    	thrust::copy(res_data.begin(), res_data.end(), h_res_data.begin());
    	printf("data size : %d  first data x: %f, y: %f, z: %f 
    ", res_data.size(), h_res_data[0].x, h_res_data[0].y, h_res_data[0].z);
    	system("pause");
    	return 0;
    }
    
    

    结果
    这次将数据打印出来,可以看到复制前的数据[0]号元素值均为0,复制后的数据[0]号元素值均为1

    copy_if()

    函数原型 [2/4]

    OutputIterator thrust::copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred)
    

    解释:这个版本的copy_if将元素从[first,last)范围内复制到一个从结果开始的范围内,但是任何导致 pred 为false的元素都不会被复制。

    int main()
    {
    	const int N = 6;
    	thrust::device_vector<tmpvec3> test_data(4000000);
    	thrust::host_vector<tmpvec3> h_test_data(4000000);
    	thrust::device_vector<tmpvec3> res_data(3990000);
    	thrust::host_vector<tmpvec3> h_res_data(3990000);
    
    	tmpvec3* raw_ptr_data = thrust::raw_pointer_cast(&test_data[0]);
    	
    	int start = 40000, end = 50000;
    	changeValue << <(end + BLOCKSIZE - 1) / BLOCKSIZE, BLOCKSIZE >> > (raw_ptr_data, start, end, 1.0);
    	thrust::copy(test_data.begin(), test_data.end(), h_test_data.begin());
    	printf("before erase data size : %d  first data x: %f, y: %f, z: %f 
    ", test_data.size(), h_test_data[0].x, h_test_data[0].y, h_test_data[0].z);
    	thrust::copy_if(test_data.begin(), test_data.end(), res_data.begin(), is_empty_point());
    	thrust::copy(res_data.begin(), res_data.end(), h_res_data.begin());
    	printf("data size : %d  first data x: %f, y: %f, z: %f 
    ", res_data.size(), h_res_data[0].x, h_res_data[0].y, h_res_data[0].z);
    	system("pause");
    	return 0;
    }
    

    结果
    看起来这个函数和 remove_copy_if() 对谓词操作是相反的

  • 相关阅读:
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之sonarqube配置
    Abp vnext 配置Swagger增加token认证
    sonarqube+gitlab runner +docker 代码质量检查问题汇总
    【EF Core】EF core中使用FluentAPI对外键进行指定配置
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之gitlab runner 关于私有docker仓库配置
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之harbor
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之gitlab + gitlab runner(docker in docker)
    【杂记】关于在实际项目中使用TDD的方法
    【系列】CentOS 7.3 离线安装(无网络环境)CI CD环境之docker+docker compose
    【TeamCity】使用TeamCity搭建ASP.NET Core + SVN 的 CICD环境
  • 原文地址:https://www.cnblogs.com/imagineincredible/p/12844234.html
Copyright © 2020-2023  润新知