Вы можете обрабатывать несколько байт в то время, и раскатать цикл:
int dataisnull(const void *data, size_t length) {
/* assuming data was returned by malloc, thus is properly aligned */
size_t i = 0, n = length/sizeof(size_t);
const size_t *pw = data;
const unsigned char *pb = data;
size_t val;
#define UNROLL_FACTOR 8
#if UNROLL_FACTOR == 8
size_t n1 = n - n % UNROLL_FACTOR;
for (; i < n1; i += UNROLL_FACTOR) {
val = pw[i + 0] | pw[i + 1] | pw[i + 2] | pw[i + 3] |
pw[i + 4] | pw[i + 5] | pw[i + 6] | pw[i + 7];
if (val)
return 0;
}
#endif
val = 0;
for (; i < n; i++) {
val |= pw[i];
}
for (i = n * sizeof(size_t); i < length; i++) {
val |= pb[i];
}
return val == 0;
}
В зависимости от вашей конкретной проблемы, это может быть более эффективным для обнаружения не нулевые значения рано или поздно:
- Если самый нулевой случай является наиболее распространенным, вы должны вычислить кумуляцию всех битов в аккумулятор
val
и протестировать только в конце.
- Если все нулевые случаи встречаются редко, вы должны чаще проверять ненулевые значения.
Развернутая версия выше представляет собой компромисс, который проверяет ненулевые значения каждые 64 или 128 байтов в зависимости от размера size_t
.
В зависимости от вашего компилятора и процессора вы можете получить более высокую производительность, уменьшая или уменьшая скорость. Вы также можете использовать встроенные функции, доступные для вашей конкретной архитектуры, чтобы использовать преимущества векторных типов, но они были бы менее переносимыми.
Обратите внимание, что код не проверяет надлежащее выравнивание для data
указателя:
- это не может быть сделано переносимо.
- предполагает, что данные были распределены через
malloc
или аналогичные, поэтому правильно выровнены для любого типа.
Как всегда, сравнивайте различные решения, чтобы понять, действительно ли это имеет значение.Эта функция, возможно, не является узким местом, написание сложной функции для оптимизации редкого случая является контрпродуктивным, что делает код менее читаемым, скорее всего, содержит ошибки и гораздо менее обслуживаемым. Например, предположение о выравнивании данных может не выполняться, если вы меняете схему распределения памяти или используете статические массивы, тогда функция может вызывать неопределенное поведение.
Вам не нужно увеличивать «данные» в цикле? –
Используйте что-то вроде SIMD для более быстрой обработки данных. – Dai
Почему вы используете 'void *' вместо 'char *' для ваших данных, если данные являются символами? – Magisch