最近在做大数据运算时,在写GPU上去行CUDA代码时,遇到一个算法问题。
在一个很大维数的数组(张量)中,需要反算(解码)出id。在这么大的维数运算量下,每减少一步运算都是一个效率的提升。
下面为了讨论简单,以3维数组来讨论。
id的生成算法如下php代码,其实就是在0~7之间给出抽出3个数值的所有可能(无序)组合情况,每一个组合给予一个id值,id值从0开始分配。
要求解的问题是:
给出任意3个数(某一个组合情况),请算出这个组合情况对应的id ?
<?php
$numbers = " 0 1 2 3 4 5 6 7 ";
$border = "+-+-+-+-+-+-+-+-+";
echo "\t",$numbers,PHP_EOL;
echo "\t",$border,PHP_EOL;
$id = 0;
for ($A = 0; $A <= 5; ++$A) {
for ($B = $A + 1; $B <= 6; ++$B) {
for ($C = $B + 1; $C <= 7; ++$C) {
$content = "| | | | | | | | |";
$content[ $A*2+1 ] = 'A';
$content[ $B*2+1 ] = 'B';
$content[ $C*2+1 ] = 'C';
echo "id:{$id}\t", $content,PHP_EOL;
echo "\t",$border,PHP_EOL;
$id = $id + 1;
}
}
}
上面代码也生成了所有情况的图形化展示(最开始我是在纸上画的,为了写博客就写一段php代码来生成这个图形化展示过程),如给出013这三个的组合情况,则算法应该返回id=1。
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
id:0 |A|B|C| | | | | |
+-+-+-+-+-+-+-+-+
id:1 |A|B| |C| | | | |
+-+-+-+-+-+-+-+-+
id:2 |A|B| | |C| | | |
+-+-+-+-+-+-+-+-+
id:3 |A|B| | | |C| | |
+-+-+-+-+-+-+-+-+
id:4 |A|B| | | | |C| |
+-+-+-+-+-+-+-+-+
id:5 |A|B| | | | | |C|
+-+-+-+-+-+-+-+-+
id:6 |A| |B|C| | | | |
+-+-+-+-+-+-+-+-+
id:7 |A| |B| |C| | | |
+-+-+-+-+-+-+-+-+
id:8 |A| |B| | |C| | |
+-+-+-+-+-+-+-+-+
id:9 |A| |B| | | |C| |
+-+-+-+-+-+-+-+-+
id:10 |A| |B| | | | |C|
+-+-+-+-+-+-+-+-+
id:11 |A| | |B|C| | | |
+-+-+-+-+-+-+-+-+
id:12 |A| | |B| |C| | |
+-+-+-+-+-+-+-+-+
id:13 |A| | |B| | |C| |
+-+-+-+-+-+-+-+-+
id:14 |A| | |B| | | |C|
+-+-+-+-+-+-+-+-+
id:15 |A| | | |B|C| | |
+-+-+-+-+-+-+-+-+
id:16 |A| | | |B| |C| |
+-+-+-+-+-+-+-+-+
id:17 |A| | | |B| | |C|
+-+-+-+-+-+-+-+-+
id:18 |A| | | | |B|C| |
+-+-+-+-+-+-+-+-+
id:19 |A| | | | |B| |C|
+-+-+-+-+-+-+-+-+
id:20 |A| | | | | |B|C|
+-+-+-+-+-+-+-+-+
id:21 | |A|B|C| | | | |
+-+-+-+-+-+-+-+-+
id:22 | |A|B| |C| | | |
+-+-+-+-+-+-+-+-+
id:23 | |A|B| | |C| | |
+-+-+-+-+-+-+-+-+
id:24 | |A|B| | | |C| |
+-+-+-+-+-+-+-+-+
id:25 | |A|B| | | | |C|
+-+-+-+-+-+-+-+-+
id:26 | |A| |B|C| | | |
+-+-+-+-+-+-+-+-+
id:27 | |A| |B| |C| | |
+-+-+-+-+-+-+-+-+
id:28 | |A| |B| | |C| |
+-+-+-+-+-+-+-+-+
id:29 | |A| |B| | | |C|
+-+-+-+-+-+-+-+-+
id:30 | |A| | |B|C| | |
+-+-+-+-+-+-+-+-+
id:31 | |A| | |B| |C| |
+-+-+-+-+-+-+-+-+
id:32 | |A| | |B| | |C|
+-+-+-+-+-+-+-+-+
id:33 | |A| | | |B|C| |
+-+-+-+-+-+-+-+-+
id:34 | |A| | | |B| |C|
+-+-+-+-+-+-+-+-+
id:35 | |A| | | | |B|C|
+-+-+-+-+-+-+-+-+
id:36 | | |A|B|C| | | |
+-+-+-+-+-+-+-+-+
id:37 | | |A|B| |C| | |
+-+-+-+-+-+-+-+-+
id:38 | | |A|B| | |C| |
+-+-+-+-+-+-+-+-+
id:39 | | |A|B| | | |C|
+-+-+-+-+-+-+-+-+
id:40 | | |A| |B|C| | |
+-+-+-+-+-+-+-+-+
id:41 | | |A| |B| |C| |
+-+-+-+-+-+-+-+-+
id:42 | | |A| |B| | |C|
+-+-+-+-+-+-+-+-+
id:43 | | |A| | |B|C| |
+-+-+-+-+-+-+-+-+
id:44 | | |A| | |B| |C|
+-+-+-+-+-+-+-+-+
id:45 | | |A| | | |B|C|
+-+-+-+-+-+-+-+-+
id:46 | | | |A|B|C| | |
+-+-+-+-+-+-+-+-+
id:47 | | | |A|B| |C| |
+-+-+-+-+-+-+-+-+
id:48 | | | |A|B| | |C|
+-+-+-+-+-+-+-+-+
id:49 | | | |A| |B|C| |
+-+-+-+-+-+-+-+-+
id:50 | | | |A| |B| |C|
+-+-+-+-+-+-+-+-+
id:51 | | | |A| | |B|C|
+-+-+-+-+-+-+-+-+
id:52 | | | | |A|B|C| |
+-+-+-+-+-+-+-+-+
id:53 | | | | |A|B| |C|
+-+-+-+-+-+-+-+-+
id:54 | | | | |A| |B|C|
+-+-+-+-+-+-+-+-+
id:55 | | | | | |A|B|C|
+-+-+-+-+-+-+-+-+
之前我的一篇博文解决过同样的问题,那次是6维,这次的维数要超过10+维。
上次解决6维的问题是,用的算法是查表法来求id,运算速度还合适。
但在更多维数的情况下查询速度就不太合适了,因为对于GPU的运算体系来说,在某些情况下从显存中读一个值(如查询表中的值)的速度慢于直接通过CUDA代码运算出这个值。这是由GPU的显存体系架构造成的。
所以在这次求解10+维的数组的id时,我就不解决用 表查询法了,直接写一个算法代码。
具体的算法代码后面再补充 ^_^,先抛出问题。
其实上面的图形化展示已经给出了数据的规律了。
————————- 待补充 ————————-