Автоматизированное полевое переупорядочение в структурах C, чтобы не дополнять

Вы можете использовать numpy (при условии a и idx как numpy.ndarray):

import numpy as np

columns_to_delete = idx.flatten()
mask = np.ones_like(a, dtype=np.bool)
mask[np.arange(a.shape[0]), columns_to_delete, :] = False
re = a[mask].reshape(a.shape[0], a.shape[1] - 1, a.shape[2])

, а затем преобразовать re в тензор, используя tf.convert_to_tensor

11
задан Christoffer 15 May 2009 в 09:30
поделиться

7 ответов

Если каждое слово вы можете выжать из хранилища критично, то я должен порекомендовать оптимизировать структуру вручную. Инструмент может оптимально расположить элементы для вас, но он не знает, например, что это значение здесь, которое вы храните в 16 битах, на самом деле никогда не превышает 1024, поэтому вы можете украсть старшие 6 бит для это значение больше здесь ...

Таким образом, человек почти наверняка победит робота в этой работе.

[Edit] Но похоже, что вы действительно не хотите вручную оптимизировать свои структуры для каждой архитектуры. Может быть, вам действительно нужно поддерживать множество архитектур?

Я действительно думаю, что эта проблема не поддается общему решению, но вы могли бы закодировать свои знания предметной области в пользовательский сценарий Perl / Python / something, который генерирует определение структуры для каждой архитектуры.

Кроме того, если все ваши члены имеют размеры, равные степени двойки, тогда вы получите оптимальную упаковку, просто отсортировав элементы по размеру (сначала самые большие). В этом случае вы можете просто использовать старые добрые построение структур на основе макросов - что-то вроде этого:

#define MYSTRUCT_POINTERS      \
    Something*  m_pSomeThing;  \
    OtherThing* m_pOtherThing; 

#define MYSTRUCT_FLOATS        \
    FLOAT m_aFloat;            \
    FLOAT m_bFloat;

#if 64_BIT_POINTERS && 64_BIT_FLOATS
    #define MYSTRUCT_64_BIT_MEMBERS MYSTRUCT_POINTERS MYSTRUCT_FLOATS
#else if 64_BIT_POINTERS
    #define MYSTRUCT_64_BIT_MEMBERS MYSTRUCT_POINTERS
#else if 64_BIT_FLOATS
    #define MYSTRUCT_64_BIT_MEMBERS MYSTRUCT_FLOATS
#else
    #define MYSTRUCT_64_BIT_MEMBERS
#endif

// blah blah blah

struct MyStruct
{
    MYSTRUCT_64_BIT_MEMBERS
    MYSTRUCT_32_BIT_MEMBERS
    MYSTRUCT_16_BIT_MEMBERS
    MYSTRUCT_8_BIT_MEMBERS
};
6
ответ дан 3 December 2019 в 08:31
поделиться

Most C compilers won't do this based on the fact that you can do weird stuff (like taking the address of an element in the struct and then use pointer magic to access the rest, bypassing the compiler). A famous example are the double linked lists in the AmigaOS which used guardian nodes as head and tail of the list (this makes it possible to avoid ifs when traversing the list). The guardian head node would always have pred == null and the tail node would have next == null, the developers rolled the two nodes into a single three-pointer struct head_next null tail_pred. By using the address of head_next or the null as the address of the head and tail nodes, they saved four bytes and one memory allocation (since they needed the whole structure only once).

So your best bet is probably to write the structures as pseudo code and then write a preprocessor script that creates the real structures from that.

2
ответ дан 3 December 2019 в 08:31
поделиться

Взгляните на пакет #pragma. Это меняет способ выравнивания элементов в структуре компилятором. Вы можете использовать его, чтобы заставить их быть плотно упакованными вместе без пробелов.

Подробнее см. Здесь

0
ответ дан 3 December 2019 в 08:31
поделиться

Существует сценарий Perl под названием pstruct, который обычно включается в установку Perl. Скрипт выведет смещения и размеры элементов структуры. Вы можете либо изменить pstruct, либо использовать его вывод в качестве отправной точки для создания утилиты, которая упаковывает ваши структуры так, как вы хотите.

$ cat foo.h 
struct foo {
    int x;
    char y; 
    int b[5];
    char c;
};

$ pstruct foo.h
struct foo {
  int                foo.x                      0       4
  char               foo.y                      4       1
                     foo.b                      8      20
  char               foo.c                     28       1
}
6
ответ дан 3 December 2019 в 08:31
поделиться

Компилятор не может переупорядочивать поля в структурах своей собственной головой. Стандарт требует, чтобы поля располагались в том порядке, в котором они определены. Выполнение чего-то еще может незаметно нарушить код.

Пока вы пишете, конечно, вполне возможно создать какой-то генератор кода, который эффективно перемещает поля. Но я предпочитаю делать это вручную.

0
ответ дан 3 December 2019 в 08:31
поделиться

Это также будет зависеть от платформы / компилятора. Как уже отмечалось, большинство компиляторов дополняют все до 4-байтового выравнивания (или хуже!), Поэтому при условии, что структура с двумя короткими и длинными:

short
long
short

займет 12 байтов (с 2 * 2 байтами заполнения).

изменение его порядка на

short
short
long

по-прежнему будет занимать 12 байт, так как компилятор дополнит его, чтобы ускорить доступ к данным (это значение по умолчанию для большинства рабочих столов, поскольку они предпочитают быстрый доступ к использованию памяти). У вашей встроенной системы разные потребности, поэтому вам все равно придется использовать пакет #pragma.

Что касается инструмента для изменения порядка, я бы просто (вручную) реорганизовал вашу структуру структуры, чтобы различные типы размещались вместе. Сначала вставьте все шорты, затем все длинные и т. Д. Если вы собираетесь собирать вещи, инструмент все равно сделает это.

0
ответ дан 3 December 2019 в 08:31
поделиться

Размышляя о том, как бы я сделал такой инструмент ... Думаю, я бы начал с отладочной информации.

Получение размера каждой структуры из источника - это очень важно. боль. Это перекрывает большую часть работы, которую уже выполняет компилятор. Я недостаточно знаком с ELF, чтобы точно сказать, как извлечь информацию о размере структуры из двоичного файла отладки, но я знаю, что эта информация существует, потому что отладчики могут ее отображать. Возможно, objdump или что-то еще в пакете binutils может легко получить это (по крайней мере, для платформ, использующих ELF).

После того, как вы получите информацию, остальное будет довольно просто. Упорядочивайте элементы от наибольшего к наименьшему, стараясь сохранить как можно более порядок исходной структуры. С Perl или Python это d даже можно было легко сопоставить его с остальной частью источника и, возможно, даже сохранить комментарии или #ifdef, в зависимости от того, насколько чисто они были использованы. Самой большой проблемой было бы изменение всех инициализаций структуры во всей кодовой базе. Ой.

Вот в чем дело. Звучит неплохо, но я не знаю ни одного такого существующего инструмента, который бы делал это, и к тому времени, когда вы напишете свой собственный ... Я думаю, вы сможете вручную изменить порядок большей части структуры в вашей программе.

0
ответ дан 3 December 2019 в 08:31
поделиться
Другие вопросы по тегам:

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