1

memcpyとして機能する1D配列から3Dにコピーすることは可能ですか?

今私は遅い方法を使用しています:

for(int loop1 = 0; loop1 < numberAgents; loop1++)
    for(int loop2 = 0; loop2 < fieldWidth; loop2++)
        for(int loop3 = 0; loop3 < fieldWidth; loop3++)
            potentialField[loop1][loop2][loop3] = cpuPotentialField[loop1 * fieldWidth * fieldWidth + loop2 * fieldWidth + loop3];

これは機能しません:

memPotentialField = numberAgents * fieldWidth * fieldWidth * sizeof(float);
memcpy(potentialField, cpuPotentialField, memPotentialField);
4

3 に答える 3

3

多次元配列は行ごとに格納されるため(§8.3.4/ 9)、基本的にはでのアプローチmemcpyは問題ありません(フロートはPODであるため)。

memcpy(&potentialField[0][0][0], cpuPotentialField,
       sizeof(potentialField)/sizeof(***potentialField));

std :: copyを使用すると、PODS以外でも機能するため、より適切です。だから私は書くだろう

std::copy(&potentialField[0][0][0],
          &potentialField[0][0][0] + sizeof(potentialField)/sizeof(potentialField[0][0][0]),
          cpuPotentialField);
于 2012-11-25T22:27:29.107 に答える
1

特に悪いコンパイラを使用しているか、最適化をオンにするのを忘れていない限り(たとえば-O3)、最初の方法はパフォーマンスの面で優れているはずです。ただし、いくつかの乗算を上げることで、少し最適化できる場合があります。

for (int loop1 = 0; loop1 < numberAgents; loop1++)
{
    const int index1 = loop1 * fieldWidth * fieldwidth;

    for (int loop2 = 0; loop2 < fieldWidth; loop2++)
    {
        const int index2 = index1 + loop2 * fieldWidth;

        for (int loop3 = 0; loop3 < fieldWidth; loop3++)
        {
            potentialField[loop1][loop2][loop3] = cpuPotentialField[index2 + loop3];
        }
    }
}
于 2012-11-25T22:14:29.603 に答える
0

ループを展開することで、ある程度のパフォーマンスを得ることができる場合があります。一部のプロセッサーでは、分岐またはジャンプ命令によって命令パイプラインが再ロードされ、時間が浪費されます。

//...
unsigned int items_remaining = fieldWidth;
for (unsigned int loop3 = 0; loop3 < fieldWidth; ++loop3)
{
    unsigned int copy_count = 4 - (items_remaining % 4);
    switch (copy_count)
    {
        // The fall-through of these cases is intentional.
        case 4:
          potentialField[loop1][loop2][loop3] = cpuPotentialField[loop1 * fieldWidth * fieldWidth + loop2 * fieldWidth + loop3];
          ++loop3;
          --items_remaining;
        case 3:
          potentialField[loop1][loop2][loop3] = cpuPotentialField[loop1 * fieldWidth * fieldWidth + loop2 * fieldWidth + loop3];
          ++loop3;
          --items_remaining;
        case 2:
          potentialField[loop1][loop2][loop3] = cpuPotentialField[loop1 * fieldWidth * fieldWidth + loop2 * fieldWidth + loop3];
          ++loop3;
          --items_remaining;
        case 1:
          potentialField[loop1][loop2][loop3] = cpuPotentialField[loop1 * fieldWidth * fieldWidth + loop2 * fieldWidth + loop3];
          ++loop3;
          --items_remaining;
    } // End: switch
} // End: for  

こちらは4点のみの展開です。ループ内の項目が多いほど、ループはより効率的になります。Paul R が言ったように、インデックスのいくつかを事前計算することも役に立ちます。

一部のプロセッサーには、コンパイラーによっては、コンパイラーが利用できる特殊なコピー命令がある場合があります。

于 2012-11-25T22:47:10.780 に答える