2 つの非常に大きな一連の要素があり、2 番目は最初の 100 倍の大きさです。最初の系列の各要素に対して、2 番目の系列には 0 個以上の要素があります。これは、2 つのネストされたループで走査および処理できます。しかし、最初の配列の各メンバーに一致する要素の量が予測できないため、処理が非常に遅くなります。
2 番目の一連の要素の実際の処理には、論理 AND (&) と人口カウントが含まれます。
Cを使用して適切な最適化を見つけることができませんでしたが、最初のシリーズの各要素に対してインラインasmを実行し、rep * mov *などを実行してから、おそらく次のバッファーで、2番目のシリーズの一致するバイトのバッチ処理を行うことを検討しています1MBとか。しかし、コードはかなり厄介になります。
誰かがより良い方法を知っていますか? C が優先されますが、x86 ASM も OK です。どうもありがとう!
問題を単純化したサンプル/デモ コード。わかりやすくするために、最初のシリーズは「人」、2 番目のシリーズは「イベント」です。(元の問題は実際には 100m と 10,000m のエントリです!)
#include <stdio.h>
#include <stdint.h>
#define PEOPLE 1000000 // 1m
struct Person {
uint8_t age; // Filtering condition
uint8_t cnt; // Number of events for this person in E
} P[PEOPLE]; // Each has 0 or more bytes with bit flags
#define EVENTS 100000000 // 100m
uint8_t P1[EVENTS]; // Property 1 flags
uint8_t P2[EVENTS]; // Property 2 flags
void init_arrays() {
for (int i = 0; i < PEOPLE; i++) { // just some stuff
P[i].age = i & 0x07;
P[i].cnt = i % 220; // assert( sum < EVENTS );
}
for (int i = 0; i < EVENTS; i++) {
P1[i] = i % 7; // just some stuff
P2[i] = i % 9; // just some other stuff
}
}
int main(int argc, char *argv[])
{
uint64_t sum = 0, fcur = 0;
int age_filter = 7; // just some
init_arrays(); // Init P, P1, P2
for (int64_t p = 0; p < PEOPLE ; p++)
if (P[p].age < age_filter)
for (int64_t e = 0; e < P[p].cnt ; e++, fcur++)
sum += __builtin_popcount( P1[fcur] & P2[fcur] );
else
fcur += P[p].cnt; // skip this person's events
printf("(dummy %ld %ld)\n", sum, fcur );
return 0;
}
gcc -O5 -march=native -std=c99 test.c -o test