エラー、バグ、質問 - ページ 2507

 
Vict:

元のアイデアを解決した(最初のコードではアドレスを正しくカウントしていなかった)。もし差し支えなければ、一緒に結果を見るのも面白いかもしれませんね。

ランによってかなり差があり、左右の違いがわからないほどです。もちろん、私はRelease版を使用しています。

#define  WRONG_ALIGNED
#define  CACHE_LINE_SIZE 64

struct Data {
#ifdef  WRONG_ALIGNED
   ushort pad;
#else
   uint pad;
#endif
   uint ar[CACHE_LINE_SIZE/sizeof(int)+1];
};

#import "msvcrt.dll"
  long memcpy(uint &, uint &, long);
#import
#define  getaddr(x) memcpy(x, x, 0)

void OnStart()
{
//   Data data[32768];
   Data data[];
  
   ArrayResize(data, 32768); // для не static-массива жуткие тормоза выходят. 
   ZeroMemory(data);
   
   ulong start_time = GetMicrosecondCount();
   
   for(unsigned i = 0; i < 10000; ++ i) {
    for (int j = ArraySize(data) - 1; j >= 0; j--)
    {
         int index = int(CACHE_LINE_SIZE - getaddr(data[j].ar[0]) % CACHE_LINE_SIZE) / sizeof(int);
         ++ data[j].ar[index];
         ++ data[j].pad;
      }
   }
      
   Alert(GetMicrosecondCount() - start_time);
   
//   Print(data[100].ar[0]);
//   Print(data[100].pad);
}
 
TheXpert:
動的配列は より多くのチェックがあります、Renatはかつて書きました、私はポストを見つけることができません、ちょうどインデックスアクセスについて話して、なぜそれがプラスよりも大幅に遅くなります。

動的配列を埋めるときは、まず静的配列を埋めてから、動的配列にArrayCopyした方が良いことがわかりました。

 
fxsaber:
この減速の原因は何でしょうか?

静的な配列から動的な 配列を作ったことになります。そのため、結果としてすべての型問題が発生します。

int a[][100];
ArrayResize(a, 100);
ZeroMemory(a);

// Первый цикл
for(int i; i < 100; ++i)
{
        for(int n; n < 100; ++n)
        {
                a[i][n]++;
        }
}

// Второй цикл
for(int n; n < 100; ++n)
{
        for(int i; i < 100; ++i)
        {
                a[i][n]++;
        }
}

第1ループと第2ループが異なる速度で動作している場合。

削除済み  
fxsaber:

ありがとうございます。もちろん、不思議なことです。安定した差がありますね。

 
Vict:

ありがとうございます。もちろん、不思議なことです。安定した差がありますね。

私も差はないです。
 
fxsaber:

動的配列を埋めるときは、まず静的配列を埋めてから、動的配列にArrayCopyした方が良いことがわかりました。

そうなんですねー。

void FillArray1( int &Array[] )
{
  const int Size = ArraySize(Array);
  
  for (int i = 0; i < Size; i++)
    Array[i] = i;
}

#define  ARRAY_SIZE 10000

void FillArray2( int &Array[] )
{
  int ArrayStatic[ARRAY_SIZE];
  
  const int Size = ArraySize(Array);
  
  for (int i = 0; i < Size;)
  {
    const int Size2 = i + ARRAY_SIZE < Size ? ARRAY_SIZE : Size - i;
    
    for (int j = 0; j < Size2; j++)
      ArrayStatic[j] = i++;
      
    if (Size2)
      ArrayCopy(Array, ArrayStatic, i - Size2, 0, Size2);
  }
}

#define  BENCH(A)                                                               \
{                                                                              \
  const ulong _StartTime = GetMicrosecondCount();                              \
  A;                                                                           \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - _StartTime)); \
}

void OnStart()
{
  int Array1[];
  ArrayResize(Array1, 1 e7);

  int Array2[];
  ArrayResize(Array2, 1 e7);
  
  BENCH(FillArray1(Array1));
  BENCH(FillArray2(Array2));
}
 
fxsaber:

そうなんです!

まあ初期化は通常1回だけなので、ほとんどの場合、スピードは気にする必要はないでしょう。(プラスメモリオーバーヘッド)

しかし、もしインデックスへのアクセスが一定で、例えば99.9%の確率で配列の最大サイズが分かっているのであれば、静的配列の 代わりに独自のシンプルなラッパーを作成することは理にかなっていると言えるでしょう。

 
TheXpert:

まあ初期化は通常1回だけなので、ほとんどの場合、速度を気にする必要はないでしょう。(プラスメモリオーバーヘッド)。

ティック解析時にレコードが遅くなることがあるのですが。何千万人もいるんだから、そりゃあ問題でしょう。

しかし、もしインデックスによる定数参照があって、例えば99.9%の確率で配列の最大サイズが分かっているなら、動的配列の代わりに静的配列の ラッパーを書くのは理にかなっていると思います。

ラップオンリードも意味があるかもしれませんね。


SZZ 読み出しで、スピードアップができない。

long ArraySum1( int &Array[] )
{
  long Sum = 0;
  
  const int Size = ArraySize(Array);
  
  for (int i = 0; i < Size; i++)
    Sum += Array[i];
    
  return(Sum);
}

#define  ARRAY_SIZE 100000

long ArraySum2( int &Array[] )
{
  long Sum = 0;

  const int Size = ArraySize(Array);  
  
  int ArrayStatic[ARRAY_SIZE];  
  
  for (int i = 0; i < Size;)
  {
    const int Size2 = i + ARRAY_SIZE < Size ? ARRAY_SIZE : Size - i;

    ArrayCopy(ArrayStatic, Array, 0, i, Size2);
    
    for (int j = 0; j < Size2; j++)
      Sum += ArrayStatic[j];
      
    i += Size2;
  }
  
  return(Sum);
}

#define  BENCH(A)                                                               \
{                                                                              \
  const ulong _StartTime = GetMicrosecondCount();                              \
  A;                                                                           \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - _StartTime)); \
}

void OnStart()
{
  int Array[];
  ArrayResize(Array, 1 e8);
  ArrayInitialize(Array, 1);
      
  BENCH(Print(ArraySum1(Array)));
  BENCH(Print(ArraySum2(Array)));
}
 
fxsaber:

そうなんです!

私の fillarray1 の方が若干速いです。

とか、読書がめんどくさいとか。

 
TheXpert:

私の fillarray1 の方が若干速いです。

Time[FillArray1(Array1)] = 39501
Time[FillArray2(Array2)] = 30304

リリース版が稼働しています。最適化を実現。