Что самый эффективный путь состоит в том, чтобы сделать битовыми операциями в массиве C

Что не так с

cc <- cor(trainDataNew)

?

Если вам нужен только нижний треугольник, вы можете использовать

cc2 <- cc[lower.tri(cc,diag=FALSE)]

Этот блог post утверждает, что выполнил задачу аналогичного размера (чуть меньше) примерно за минуту. Их подход реализован в HiClimR::fastCor.

library(HiClimR)
system.time(cc <- fastCor(dd, nSplit = 10, 
        upperTri = TRUE, verbose = TRUE,
        optBLAS=TRUE))

Я еще не получил эту работу (продолжайте исчерпывать память), но вам, возможно, повезет больше. Вам также следует обратить внимание на связь R с оптимизированным BLAS, например, см. здесь для MacOS.

Кто-то здесь сообщает о распараллеленной версии (код здесь , вместе с некоторыми разветвленными версиями)

10
задан starblue 21 March 2009 в 07:58
поделиться

3 ответа

for ( i = 10 ; i-- > 0 ; )
    result_array[i] = byte_array[i] & byte_mask[i];
  • Движение назад предварительно загружает строки кэша процессора.
  • Включая декремент в сравнивании может сохранить некоторые инструкции.

Это будет работать на все массивы и процессоры. Однако, если Вы знаете, что Ваши массивы выравниваются словом, более быстрый метод должен бросить к большему типу и сделать то же вычисление.

Например, скажем, n=16 вместо n=10. Затем это было бы намного быстрее:

uint32_t* input32 = (uint32_t*)byte_array;
uint32_t* mask32 = (uint32_t*)byte_mask;
uint32_t* result32 = (uint32_t*)result_array;
for ( i = 4 ; i-- > 0 ; )
    result32[i] = input32[i] & mask32[i];

(Конечно, Вам нужен надлежащий тип для uint32_t, и если n не питание 2, необходимо очистить начало и/или окончание так, чтобы 32-разрядный материал был выровненный.)

Изменение: вопрос конкретно призывает, чтобы результаты были помещены в отдельный массив, однако это почти наверняка было бы быстрее для изменения оперативного входного массива.

14
ответ дан 3 December 2019 в 19:35
поделиться

Если Вы хотите сделать его быстрее, удостоверьтесь, что byte_array имеет длину, которая является несколькими из 4 (8 на 64-разрядных машинах), и затем:

char byte_array[12];
char byte_mask[12];
/* Checks for proper alignment */
assert(((unsigned int)(void *)byte_array) & 3 == 0);
assert(((unsigned int)(void *)byte_mask) & 3 == 0);
for (i = 0; i < (10+3)/4; i++) {
  ((unsigned int *)(byte_array))[i] &= ((unsigned int *)(byte_mask))[i];
}

Это намного быстрее, чем выполнение его байт на байт.

(Обратите внимание, что это существует мутация; если Вы хотите сохранить исходный byte_array также, то, очевидно, необходимо сохранить результаты в другом массиве вместо этого.)

5
ответ дан 3 December 2019 в 19:35
поделиться
\#define CHAR_ARRAY_SIZE    (10)
\#define INT_ARRAY_SIZE     ((CHAR_ARRAY_SIZE/ (sizeof (unsigned int)) + 1)

typedef union _arr_tag_ {

    char          byte_array [CHAR_ARRAY_SIZE];
    unsigned int  int_array [INT_ARRAY_SIZE]; 

} arr_tag;

Теперь int_array для маскирования. Это могло бы работать и на процессоры на 64 бита и на на 32 бита.

arr_tag arr_src, arr_result, arr_mask;

for (int i = 0; i < INT_ARRAY_SIZE; i ++) {
    arr_result.int_array [i] = arr_src.int_array[i] & arr_mask.int_array [i];
}

Попробуйте это, код мог бы также выглядеть чистым.

1
ответ дан 3 December 2019 в 19:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: