c: многомерный массив с использованием 1d массива под крышками - PullRequest
3 голосов
/ 11 февраля 2012

Я пытаюсь распределить огромный 4d массив (доступно 192 гигабайта);но то, что входит, не соответствует тому, что выходит (см. assert () в коде ниже).(Я сделал определенные размеры маленькими; но реальные числа: 20,9000,195,120)

#define SIZE_A 1
#define SIZE_B 3
#define SIZE_C 4
#define SIZE_D 2

#define offSet(a,b,c,d) ( ((size_t) SIZE_A * SIZE_B * SIZE_C * a) + ((size_t) SIZE_B * SIZE_C * b) + ((size_t) SIZE_C * c) + d)

void xall(void)
{
int *aray = (int *) malloc( (size_t) SIZE_A * SIZE_B * SIZE_C *  SIZE_D  * sizeof(int));


int counter = 0;

    for (int a = 0; a < SIZE_A; ++a){
        for (int b = 0; b < SIZE_B; ++b){
            for (int c = 0; c < SIZE_C; ++c) {
                for (int d = 0; d < SIZE_D; ++d){
                    aray[ offSet(a,b,c,d) ] = counter++;

                }}}}


counter = 0;    
    for (int a = 0; a < SIZE_A; ++a){
        for (int b = 0; b < SIZE_B; ++b){
            for (int c = 0; c < SIZE_C; ++c) {
                for (int d = 0; d < SIZE_D; ++d){       
                    int value = aray[ offSet(a,b,c,d) ] ;
                    assert(value == counter++);

                }}}}
}

Ответы [ 4 ]

5 голосов
/ 11 февраля 2012

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

#include <assert.h>
#include <stdlib.h>

#define SIZE_A 1
#define SIZE_B 3
#define SIZE_C 4
#define SIZE_D 2

int main(void)
{
  int counter = 0;
  int (*array)[SIZE_A][SIZE_B][SIZE_C][SIZE_D] = 
          malloc(sizeof(int) * SIZE_A * SIZE_B * SIZE_C *  SIZE_D);

  for (int a = 0; a < SIZE_A; ++a)
    for (int b = 0; b < SIZE_B; ++b)
      for (int c = 0; c < SIZE_C; ++c) 
        for (int d = 0; d < SIZE_D; ++d)
          (*array)[a][b][c][d] = counter++;

  counter = 0;    
  for (int a = 0; a < SIZE_A; ++a)
    for (int b = 0; b < SIZE_B; ++b)
      for (int c = 0; c < SIZE_C; ++c)
        for (int d = 0; d < SIZE_D; ++d)
        {
          int value = (*array)[a][b][c][d];
          assert(value == counter++);
        }

  return 0;
}

Расположение в памяти массива, выделенного в этом примере, точно такое же, как и в вашем вопросе, но почему бы не позволить компилятору сделать всю работу за вас?

Немного о редакционной статье - не приводите возвращаемое значение вызова malloc() в программе на Си. Преобразование из void * является неявным, и наличие явного приведения может скрыть предупреждения о неявном объявлении функции, которые вы получите в противном случае - например, если вы забыли включить stdlib.h.

1 голос
/ 11 февраля 2012

Ваш макрос не совсем правильный. Измените это на это:

#define offSet(a,b,c,d) ( ((size_t) SIZE_B * SIZE_C * SIZE_D * a) + ((size_t) SIZE_C * SIZE_D * b) + ((size_t) SIZE_D * c) + d)

Вы в основном переместили SIZE_X на 1 букву.

Я также предлагаю поместить () вокруг параметров макроса:

#define offSet(a,b,c,d) ( ((size_t) SIZE_B * SIZE_C * SIZE_D * (a)) + ((size_t) SIZE_C * SIZE_D * (b)) + ((size_t) SIZE_D * (c)) + (d) )
0 голосов
/ 11 февраля 2012

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

Другие, даже не выделяют реальную память при вызове malloc, как, например, Linux, и позже вы можете потерпеть неудачу при попытке записи в него, но я думаю, это не ваш случай.

Попробуйте проверить, можете ли вы контролировать максимальный объем выделяемой памяти на процесс в вашей системе. Надеюсь, вы найдете ответ, это действительно интересно.

Некоторые материалы для чтения:

http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory http://www.linux -mag.com / ID / 827 /

0 голосов
/ 11 февраля 2012

Мне кажется, макросы должны быть определены следующим образом:

#define offSet(a,b,c,d) ( ((size_t)  SIZE_B * SIZE_C *SIZE_D * a) + ((size_t)  SIZE_C *SIZE_D * b) + ((size_t) SSIZE_D * c) + d)
...