Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将数组中的简单数据类型移动到特定位置的最快方法_C++_C_Arrays_Performance - Fatal编程技术网

C++ 将数组中的简单数据类型移动到特定位置的最快方法

C++ 将数组中的简单数据类型移动到特定位置的最快方法,c++,c,arrays,performance,C++,C,Arrays,Performance,将已知大小的数组中的简单数据类型移动到特定位置的最快方法是什么 我的具体案例是旋转存储为int[9]的游戏板 [0,1,2,3,4,5,6,7,8]变为[6,3,0,7,4,1,8,5,2] 在我的用例中,我有一个这些数组的向量,每个数组都需要旋转 电路板布局: board1|corners|centers 0 1 2 | 0 2 | 1 3 4 5 | | 3 5 6 7 8 | 6 8 | 7 board2|corners|centers 6 3 0

将已知大小的数组中的简单数据类型移动到特定位置的最快方法是什么

我的具体案例是旋转存储为int[9]的游戏板
[0,1,2,3,4,5,6,7,8]
变为
[6,3,0,7,4,1,8,5,2]


在我的用例中,我有一个这些数组的向量,每个数组都需要旋转

电路板布局:

board1|corners|centers
0 1 2 | 0   2 |   1  
3 4 5 |       | 3   5
6 7 8 | 6   8 |   7

board2|corners|centers
6 3 0 | 6   0 |   3
7 4 1 |       | 7   1
8 5 2 | 8   2 |   5
我想到的最快的方法是创建一个公共变量来分配数组项,然后将内存复制回来

int layout[9];
int pub_layout[9];

#include <cstring> // for std::memcpy
void rotate(int layout[])
{
    pub_layout[4] = layout[4]; // center

    pub_layout[0] = layout[6]; // corner four
    pub_layout[6] = layout[8];
    pub_layout[8] = layout[2];
    pub_layout[2] = layout[0];

    pub_layout[1] = layout[3]; // center four
    pub_layout[3] = layout[7];
    pub_layout[7] = layout[5];
    pub_layout[5] = layout[1];

    std::memcpy(layout,pub_layout,sizeof(pub_layout));
}
int布局[9];
int pub_布局[9];
#包含//用于std::memcpy
空心旋转(整型布局[])
{
pub_布局[4]=布局[4];//中心
pub_布局[0]=布局[6];//四角
pub_布局[6]=布局[8];
pub_布局[8]=布局[2];
发布版面[2]=版面[0];
pub_布局[1]=布局[3];//中间四
pub_布局[3]=布局[7];
pub_布局[7]=布局[5];
pub_布局[5]=布局[1];
标准::memcpy(布局,pub_布局,sizeof(pub_布局));
}
我看到了一个类似的问题,建议
int[]b=新的int[]{b[6],b[3],b[0],b[7],b[4],b[1],b[8],b[5],b[2]}
..尽管时钟慢得多(不到单个线程速度的一半)


两者都相对较快()

如果这不是最快的方法,那是什么?

我猜想C和C++中的算法都是相同的。

< P>使用这个,你得到MeMcPy调用和[4 ]到[4 ]赋值。您丢失了对
putAside
变量的两个赋值。所以它肯定会快一点

int layout[9];
int putAside;

void rotate(int[] layout)
{
    putAside = layout[0];
    layout[0] = layout[6]; // corner four
    layout[6] = layout[8];
    layout[8] = layout[2];
    layout[2] = putAside;

    putAside = layout[1];
    layout[1] = layout[3]; // center four
    layout[3] = layout[7];
    layout[7] = layout[5];
    layout[5] = putAside;
}

最快的方法可能是在非常紧密的循环中使用处理器缓存:

void rotate(int in[3][3], int out[3][3])
{
    int i, j, k;
    for (i=0,k=2;i<3;i++,k--)
        for (j=0;j<3;j++)
            out[j][k] = in[i][j];
}
如果要求
in
out
可以相同,则应使用以下选项:

void rotate(int in[9], int out[9])
{
    int tmp[9];
    int i, j, k;
    for (i=0,k=2;i<3;i++,k--)
        for (j=0;j<3;j++)
            tmp[j*3+k] = in[i*3+j];
    //memcpy(out,tmp, sizeof(tmp));  // use this...
    for(i=0;i<9;i++) out[i]=tmp[i];  //..or this, whichever clocks faster
}
void旋转(int-in[9],int-out[9])
{
int-tmp[9];
int i,j,k;

对于(i=0,k=2;i如果您想要一种更灵活的方法来应用任何转换,那么下面类似的方法也会非常快:

template <int _1, int _2, int _3, int _4, int _5, int _6, int _7, int _8, int _9>
struct transfomer {
    board& _in;
    operator board() const {
      return { _in[_1], _in[_2], _in[_3], _in[_4], _in[_5], _in[_6], _in[_7], _in[_8], _in[_9] };
    }
};

void rotate3(board& layout) {
  layout = transfomer<6, 3, 0, 7, 4, 1, 8, 5, 2>{layout};
}

是的,它依赖于隐式转换操作符(这在我看来通常是有害的,但在这里很有用。)(注意:我对您的测试进行了一点调整,以使用
数组
,运行相同的测试表明,上述代码与@Joel中的手动解决方案大致相同,但平均而言没有稍好)

我发现您发布的测试代码有几个问题。
rotate2()
函数涉及动态内存分配(顺便说一句,所有这些都会在示例代码中泄漏),而
rotate2()则没有。因此,
rotate2()并不奇怪
的速度较慢。是一个稍微修改的代码,使用C++11容器和算法。在本例中,
rotate()
rotate2()
是可比较的,不涉及任何动态内存分配。您是否考虑过不按行顺序存储它们?如果您按
0、1、2、5、8、7、6、3、4
的顺序存储它们,并使用
char
而不是
int
来代替
int
,则旋转电路板只需要将前8个元素移动3个元素,留下最后一个元素t(职位4)不变量。此外,如果将这8个元素存储在一个
long
中,则可以通过两个24位移位操作和一点位屏蔽来实现旋转。可以使用我前面评论中的示例的稍微更清晰的版本。算法独立于实现它们的语言,因此您的SUSPECion是错误的。也就是说,最快的方法是不旋转它们,而是相应地偏移访问。第二个版本的
rotate()的问题
是因为它接受与第一个不同类型的参数。因此,对于调用方来说,这并不是一个简单的替换-必须进行类型转换才能强制编译器接受它。@Peter,我只是给出一个不同的版本来匹配OPs的起始点,它使用了
int[9]
as board。由他决定使用哪一种。使用-O3时速度非常快(比Peter在我的系统上对Joël的修改快12%),但不幸的是
0 1 2 3 4 5 6 7 8
在传递相同的参数
0 1 6 3 6 3 6
时变为
0 1 6 3 3 6
@ti7,是的,我的算法假设
in
out
是不同的。@ti7,修复了
in
out
可能是相同的,但要以复制操作为代价。注意:如果速度更快,请给出类似于此答案的upvoteI,但这是确保它的唯一方法(或任何其他方法)更快的方法是进行测量。但这是最干净的方法,而且编译器有机会疯狂地进行优化。可能还希望将
putte
设置为局部(自动)变量,因为将其设置为静态变量几乎没有任何价值。另外,请注意,您复制了OP的错误-类型
int[]布局
不是函数参数的有效类型。与此答案相比,在我的系统上使用-O3时速度要快得多(2.6倍),在编译时不使用该标志时速度要快一点(14%)。@Peter的建议使用-O3时速度要快一点(9%),使用-O3时速度要慢一点(5%)。
template <int _1, int _2, int _3, int _4, int _5, int _6, int _7, int _8, int _9>
struct transfomer {
    board& _in;
    operator board() const {
      return { _in[_1], _in[_2], _in[_3], _in[_4], _in[_5], _in[_6], _in[_7], _in[_8], _in[_9] };
    }
};

void rotate3(board& layout) {
  layout = transfomer<6, 3, 0, 7, 4, 1, 8, 5, 2>{layout};
}
typedef array<int, 9> board;