- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
假设我们有这个排序数组
0 1 1 1 1 2 2 2 2 2 3 10 10 10
我想高效地找到元素变化的位置。例如在我们的数组中,位置如下:
0 1 5 10 11
我知道有一些库 (Thrust) 可以实现这一点,但是我想出于教育目的创建自己的高效实现。
您可以在这里找到完整的代码:http://pastebin.com/Wu34F4M2
它也包括验证。
内核是以下函数:
__global__ void findPositions(int *device_data,
int totalAmountOfValuesPerThread, int* pos_ptr, int N){
int res1 = 9999999;
int res2 = 9999999;
int index = totalAmountOfValuesPerThread*(threadIdx.x +
blockIdx.x*blockDim.x);
int start = index; //from this index each thread will begin searching
if(start < N){ //if the index is out of bounds do nothing
if(start!=0){ //if start is not in the beginning, check the previous value
if(device_data[start-1] != device_data[start]){
res1 = start;
}
}
else res1 = start; //since it's the
//beginning we update the first output buffer for the thread
pos_ptr[index] = res1;
start++; //move to the next place and see if the
//second output buffer needs updating or not
if(start < N && device_data[start] != device_data[start-1]){
res2 = start;
}
if((index+1) < N)
pos_ptr[index+ 1] = res2;
}
}
我创建了很多线程,因此每个线程都必须处理数组的两个值。
device_data
数组中存储了所有的数字totalAmountOfValuesPerThread
在这种情况下是每个线程必须处理的值的总量pos_ptr
与device_data
的长度相同,每个线程将缓冲区的结果写入此device_vector
N
是device_data
数组中的数字总数在名为 res1
和 res2
的输出缓冲区中,每个线程要么保存一个之前未找到的位置,要么保持原样。
例子:
0 <---- thread 1
1
1 <---- thread 2
1
2 <---- thread 3
2
3 <---- thread 4
每个线程的输出缓冲区,假设大数字 9999999 是 inf
将是:
thread1 => {res1=0, res2=1}
thread2 => {res1=inf, res2=inf}
thread3 => {res1=4, res2=inf}
thread4 => {res1=6, res2=inf}
每个线程都会更新 pos_ptr
device_vector
因此该 vector 将具有以下结果:
pos_ptr =>{0, 1, inf, inf, 4, inf, 6, inf}
完成内核后,我使用库 Thrust
对 vector 进行排序,并将结果保存在名为 host_pos
的主机 vector 中。所以 host_pos
vector 将具有以下内容:
host_pos => {0, 1, 4, 6, inf, inf, inf, inf}
这个实现很糟糕,因为
device_vector
,它与输入一样大并且也驻留在全局内存中。每个线程访问这个 vector 以写入结果,这是非常低效的。这是当每个 block 中有 512
线程时输入大小 1 000 000
的测试用例。
CPU time: 0.000875688 seconds
GPU time: 1.35816 seconds
输入大小 10 000 000
的另一个测试用例
CPU time: 0.0979209
GPU time: 1.41298 seconds
请注意,CPU 版本几乎慢了 100 倍,而 GPU 的速度几乎相同。
不幸的是我的 GPU 没有足够的内存,所以让我们试试 50 000 000
CPU time: 0.459832 seconds
GPU time: 1.59248 seconds
据我了解,对于大量输入,我的 GPU 实现可能会变得更快,但我相信更高效的方法可能会使实现更快,即使对于较小的输入也是如此。
为了让我的算法运行得更快,你会建议什么设计?不幸的是,我想不出更好的办法。
提前致谢
最佳答案
我真的不明白您认为这很糟糕的任何原因。线程太多?线程过多的定义是什么?每个输入元素一个线程是 CUDA 程序中非常常见的线程策略。
因为您似乎愿意考虑在大部分工作中使用 thrust(例如,您愿意在完成数据标记后调用 thrust::sort)并考虑到 Benc 的观察(您正在花费很多时间试图优化总运行时间的 3%)也许你可以通过更好地利用推力来产生更大的影响。
建议:
device_data
数组,并在它们移动时标记边界。这可能会显着改善您的内核。但同样,优化 3% 不一定是您要花费大量精力的地方。pos_ptr
数组,让我们注意除了inf
值它已经排序。所以也许有更聪明的选项而不是“推力::排序”,然后修剪数组,以产生结果。看一下推力函数,例如remove_if
和 copy_if
。我没有对它进行基准测试,但我的猜测是它们会比 sort 便宜得多,其次是修剪数组(删除 inf 值)。关于c++ - 使用 CUDA 以有效计算元素更改的已排序数组的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15939411/
SQL 和一般开发的新手,我有一个表(COUNTRIES),其中包含字段(INDEX、NAME、POPULATION、AREA) 通常我添加一个客户端(Delphi)计算字段(DENSITY)和 On
我想使用 calc(100%-100px),但在我的 demo 中不起作用由于高度只接受像素,因此如何将此百分比值转换为像素。 最佳答案 以下将为您提供高度: $(window).height();
我正在尝试在 MySQL 中添加列并动态填充其他列。 例如我有一张表“数字”并具有第 1 列、第 2 列、第 3 列,这些总数应填充在第 4 列中 最佳答案 除非我误解了你的问题,否则你不只是在寻找:
我想返回简单计算的结果,但我不确定如何执行此操作。我的表格如下: SELECT COUNT(fb.engineer_id) AS `total_feedback`, SUM(fb.ra
我一直在尝试做这个程序,但我被卡住了,我仍然是一个初学者,任何帮助将不胜感激。我需要程序来做 打印一个 10 X 10 的表格,其中表格中的每个条目都是行号和列号的总和 包含一个累加器,用于计算所有表
这个计算背后一定有一些逻辑。但我无法得到它。普通数学不会导致这种行为。谁能帮我解释一下原因 printf ("float %f\n", 2/7 * 100.0); 结果打印 1.000000 为什么会
我想计算从 0 到 (n)^{1/2} - 1 的数字的 AND每个数字从 0 到 (n)^{1/2} - 1 .我想在 O(n) 中执行此操作时间,不能使用 XOR、OR、AND 运算。 具体来说,
如何在 Excel 中将公式放入自定义数字格式?例如(出于说明目的随机示例), 假设我有以下数据: 输入 输出 在不编辑单元格中的实际数据的情况下,我想显示单元格中的值除以 2,并保留两位小数: 有没
每次我在 Flutter 应用程序中调用计算()时,我都会看到内存泄漏,据我所知,这基本上只是一种生成隔离的便捷方法。我的应用程序内存占用增加并且在 GC 之后永远不会减少。 我已将我的代码简化为仅调
我有数字特征观察 V1通过 V12用于目标变量 Wavelength .我想计算 Vx 之间的 RMSE列。数据格式如下。 每个变量“Vx”以 5 分钟的间隔进行测量。我想计算所有 Vx 变量的观测值
我正在寻找一种使用 C 语言计算文件中未知字符数的简单方法。谢谢你的帮助 最佳答案 POSIX 方式(可能是您想要的方式): off_t get_file_length( FILE *file ) {
我正在使用 Postgres,并且我正试图围绕如何在连续日期跨度中得出第一个开始日期的问题进行思考。例如 :- ID | Start Date | End Date =================
我有一个订单表格,我在其中使用 jQuery 计算插件来汇总总数。 此求和工作正常,但生成的“总和”存在问题。总之,我希望用逗号替换任何点。 代码的基础是; function ($this) {
我在使用 double 变量计算简单算术方程时遇到问题。 我有一个具有 double 属性 Value 的组件,我将此属性设置为 100。 然后我做一个简单的减法来检查这个值是否真的是 100: va
我在这里看到了一些关于 CRC 32 计算的其他问题。但没有一个让我满意,因此是这样。 openssl 库是否有任何用于计算 CRC32 的 api 支持?我已经在为 SHA1 使用 openssl,
当我在PHP日期计算中遇到问题时,我感到惊讶。 $add = '- 30 days'; echo date('Y-m-01', strtotime($add)); // result is 2017-
我正在使用 javascript 进行练习,我编写了这个脚本来计算 2 个变量的总和,然后在第三个方程中使用这个总和!关于如何完成这项工作的任何想法都将非常有用! First Number:
我有一个来自EAC的提示单和一个包含完整专辑的FLAC文件。 我正在尝试制作一些python脚本来播放文件,因为我需要能够设置在flac文件中开始的位置。 如何从CueSheet格式MM:SS:FF转
这个问题已经有答案了: Adding two numbers concatenates them instead of calculating the sum (24 个回答) 已关闭去年。 我有一个
4000 我需要上面字段 name="quantity" 和 id="price" 中的值,并使用 javascript 函数进行计算,并将其显示在字段 id= 中仅当我单击计算按钮时才显示“总
我是一名优秀的程序员,十分优秀!