Вы, кажется, используете лотов данных. Это предположение, но я бы сказал, что вы получите оптимальное поведение, предварительно обработав ваши выражения в оптимальных проходах кеша. Рассмотрим два выражения Дано:
S[1] = A[10] AND B[52] AND F[15] AND U[2]
S[2] = I[8] AND Z[4]
переписывают их как:
S[1] = 1;
S[1] &= A[10];
S[1] &= B[52];
S[1] &= F[15];
S[1] &= U[2];
S[2] = 1;
S[2] &= I[8];
S[2] &= Z[4];
Тогда-то все выражения вместе, чтобы создать один длинный список операций:
S[1] = 1;
S[2] = 1;
S[1] &= A[10];
S[1] &= B[52];
S[1] &= F[15];
S[2] &= I[8];
S[1] &= U[2];
S[2] &= Z[4];
Рассмотрим размер кэш компьютера. Нам нужны все входные векторы в кеше. Вероятно, этого не может быть, поэтому мы знаем, что мы будем тянуть входные векторы и векторы результата в и из памяти несколько раз. Мы хотим разделить доступный кэш компьютера на три части: блок ввода вектора, блок векторного результата и некоторое рабочее пространство (из которого будет выведен текущий текущий список операций).
Теперь пройдите список выражений, вытягивающих выражения, которые попадают в диапазон A-I и S [1] -S [400]. Затем снова проведите J-T (или все, что подходит в кеше) и потяните эти операции дальше, как только вы дойдете до конца повтора списка операций для s [401] -s [800]. Это окончательный порядок выполнения операций. Обратите внимание, что это может быть распараллелировано без конкуренции по S-диапазонам.
Недостатком является то, что вы не получите раннее поведение. Потенциал роста - это только сбои кэша при переходе блоков вычислений. Для такого большого набора данных я подозреваю, что это (и устранение всего ветвления) будет подавлять раннее преимущество.
Если вы все еще хотите попытаться использовать раннюю оптимизацию, вы можете использовать , это сложнее реализовать. Подумайте: когда у вас есть свой кэш скобка AI & S [1] -s [400], и вы создали список операций по всем этой скобе:
S[1] &= A[10];
S[1] &= B[52];
S[1] &= F[15];
S[2] &= I[8];
Вы можете изменить порядок операций в группу им S [x] (этот пример уже был). Теперь, если вы обнаружите, что A [10] является ложным, вы можете «рано выйти» в блок S [2]. Насколько это реализовать? Ну, ваши операции теперь нужно знать, сколько пропустить вперед от текущей операции:
Operation[x ] => (S[1] &= A[10], on false, x+=3)
Operation[x+1] => (S[1] &= B[52], on false, x+=2)
Operation[x+2] => (S[1] &= F[15], on false, x+=1)
Operation[x+3] => (S[2] &= I[8]...
Опять же, я подозреваю, просто добавив разветвления будет медленнее, чем просто выполнение всех других работ. Это не полный процесс с самого начала, так как вы переходите к следующему блоку блока ввода, вам нужно будет пересмотреть каждое полученное значение S [x], чтобы определить, было ли оно уже неудачно и должно быть пропущено.
Такие подходы, как правило, скрывают настоящую проблему. Возможно, у вас неправильный взгляд на реальную проблему? Однако вы можете использовать массив переменной длины для каждого термина, указывающего на обязательные поля. – Olaf
Выражения дают прямые индексы в массивы, правильно? Это просто постоянный поиск в прямой памяти. Просто и вместе эти места памяти.Есть что-то, что мне не хватает? –
Я с @greybeard. Я не получаю * «Алгоритм должен запускаться один раз для каждого входного значения, и есть миллионы входных значений». * Вы имеете в виду, что у вас есть несколько наборов «<100 векторов»? –