Форум программистов, компьютерный форум CyberForum.ru

Передача в поток многомерных массивов по указателю - C++

Восстановить пароль Регистрация
 
Kapex
15 / 15 / 4
Регистрация: 11.11.2014
Сообщений: 121
30.09.2016, 16:39     Передача в поток многомерных массивов по указателю #1
Доброго всем времени суток.

У меня возникло непонимание того, как можно передать двумерный (многомерный) массив в поток. Пока это выглядит вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void worker (void* array2d, int size1, int size2){
       int ** arrayToWork = reinterpret_cast<int**> (array2d);
       
       for (int i = 0; i < size1; ++i)
            for (int j = 0; j < size2; ++j)
                  read_and_process(array2d[i][j]);
 
      /* do usefull stuff */
}
int main(){
     int  arr2d[size1][size2];
           /* fill in the arr2d*/
 
     vector<thread> poolThreads;
     for (int iThread = 0; iThread < 4; iThread++)
          pollThreads.push_back(thread(worker,  reinterpret_cast<void*> (arr2d), size1, size2));
     for (int iThread = 0; iThread < 4; iThread++)
          pollThreads[iThread].join();
        
   
  return 0;
}
Есть ли какой-нибудь более правильный способ передачи двумерных (многомерных) массивов в поток без использования приведений?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.09.2016, 16:39     Передача в поток многомерных массивов по указателю
Посмотрите здесь:

Передача массива в функцию по указателю C++
C++ Обработка многомерных массивов
C++ Обработка многомерных массивов
Редактор многомерных динамических массивов C++
C++ Шестнадцатеричный вывод WORD и DWORD в поток без приведения к указателю
Передача по указателю и по ссылке C++
указатели многомерных массивов C++
Передача struct по указателю C++
C++ Быстрая инициализация многомерных массивов
Pthread, поток, передающий значение по указателю C++
Программирование обработки многомерных массивов C++
Передача многомерных массивов в функцию C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
6783 / 3994 / 916
Регистрация: 30.01.2014
Сообщений: 6,812
30.09.2016, 19:16     Передача в поток многомерных массивов по указателю #2
Kapex, ну например так:
C++
1
2
3
4
5
6
7
8
9
10
11
size_t const size1 = 4;
size_t const size2 = 5;
 
void worker (int (*array2d)[size2], int size1){
      
       for (int i = 0; i < size1; ++i)
            for (int j = 0; j < size2; ++j)
                  read_and_process(array2d[i][j]);
 
      /* do usefull stuff */
}
C++
1
pollThreads.push_back(thread(worker, arr2d, size1));
Но в целом все зависит от конечной цели. В том числе и "правильность".

Добавлено через 45 минут
Kapex, в принципе, если бы мне понадобилось (если бы) что-то подобное, то я бы сделал так:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
template <typename T>
class LightArray2d
{
public:
    LightArray2d(size_t r, size_t c)
        : m_rows(r)
        , m_columns(c)
        , m_data(new T[r * c])
    { }
    LightArray2d(LightArray2d && x)
        : m_columns(x.m_columns)
        , m_rows(x.m_rows)
        , m_data(std::move(x.m_data))
    { }
    
    T * operator[](size_t i)
    {
        return &m_data[i * m_columns];
    }
    T const * operator[](size_t i) const
    {
        return &m_data[i * m_columns];
    }
    
    T const & operator()(size_t i, size_t j) const
    {
        return m_data[i * m_columns + j];
    }
    T & operator()(size_t i, size_t j)
    {
        return m_data[i * m_columns + j];
    }                          
                      
    size_t columns() const
    {
        return m_columns;
    }
    size_t rows() const
    {
        return m_rows;
    }
    
    T * begin() 
    { 
        return &m_data[0]; 
    }
    T * end() 
    { 
        return &m_data[m_rows * m_columns]; 
    }
    T const * begin() const
    { 
        return &m_data[0]; 
    }
    T const * end() const
    { 
        return &m_data[m_rows * m_columns]; 
    }
   
private:
    size_t const m_rows;
    size_t const m_columns;
 
    std::unique_ptr<T[]> m_data;
};

или так (если размерности известны на этапе компиляции):
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// Версия без динамической памяти (для размеров, известных на этапе компиляции)
template <typename T, size_t R, size_t C>
class LightArray2d
{
public:
    T * operator[](size_t i)
    {
        return &m_data[i * C];
    }
    T const * operator[](size_t i) const
    {
        return &m_data[i * C];
    }
    
    T const & operator()(size_t i, size_t j) const
    {
        return m_data[i * C + j];
    }
    T & operator()(size_t i, size_t j)
    {
        return m_data[i * C + j];
    }                          
                      
    size_t columns() const
    {
        return C;
    }
    size_t rows() const
    {
        return R;
    }
    
    T * begin() 
    { 
        return &m_data[0]; 
    }
    T * end() 
    { 
        return &m_data[R * C]; 
    }
    T const * begin() const
    { 
        return &m_data[0]; 
    }
    T const * end() const
    { 
        return &m_data[R * C]; 
    }
   
private:
    std::array<T, R * C> m_data;
};

И потом спокойно бы работал с этим так:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//void worker(LightArray2d<int, 5, 6> const & array2d)
void worker(LightArray2d<int> const & array2d)
{
    // var [1] 
    for(size_t i = 0; i < array2d.rows(); ++i)
    {
        for(size_t j = 0; j < array2d.columns(); ++j)
        {
            // Это исключительно для визуализации, конечно же в реальности из потока в консоль лучше ничего не писать.
            std::cout << array2d[i][j] << ' '; 
        }
    }
    std::cout << std::endl;
    // var [2]
    for(size_t i = 0; i < array2d.rows(); ++i)
    {
        for(size_t j = 0; j < array2d.columns(); ++j)
        {
            std::cout << array2d(i, j) << ' ';
        }
    }
    std::cout << std::endl;
    // var [3]
    for(int a : array2d)
    {
        std::cout << a << ' ';
    }
    /* do usefull stuff */
}
 
int main() {
    LightArray2d<int> arr2d(5, 6);
    //LightArray2d<int, 5, 6> arr2d;
    
    /* fill in the arr2d*/
    int c = 0;
    std::generate(arr2d.begin(), arr2d.end(), [&c](){ return ++c; });
    
    enum { ThreadsCount = 1 }; // 1, чтобы в демопримере не испортить вывод.
    
    vector<thread> poolThreads;
    for(int iThread = 0; iThread < ThreadsCount; iThread++)
    {
        poolThreads.emplace_back(thread(worker, std::ref(arr2d)));
    }
    
    for(int iThread = 0; iThread < ThreadsCount; iThread++)
    {
        poolThreads[iThread].join();
    }
}

Онлайн демопример: http://rextester.com/QSCDC23483
nmcf
30.09.2016, 20:11
  #3

Не по теме:

DrOffset, как-то длинновато вышло в сравнении с его примером.

DrOffset
30.09.2016, 20:21
  #4

Не по теме:

Цитата Сообщение от nmcf Посмотреть сообщение
как-то длинновато вышло в сравнении с его примером.
С учетом того, что подобный класс выносится в библиотечку проекта и использует потом всюду, длина компенсируется.
Так-то, если ты возьмешь, к примеру, std::array и вставишь его код к себе в проект, то тоже получится много.
Если это лаба, и ему нужно это в одном месте, то уж извините, можно тогда игнорировать этот пост.

IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6226 / 2955 / 287
Регистрация: 04.12.2011
Сообщений: 7,880
Записей в блоге: 3
30.09.2016, 22:50     Передача в поток многомерных массивов по указателю #5
Kapex, вот интересная ещё инфа
Передача двумерного массива в функцию. Ошибка "invalid types for array subscript"
Штука в том, что массив C++ внутренне всегда одномерен. То есть, индексы можно пересчитывать, а указатель кастить. Вот вариант - вырви-глаз:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
template<class T, size_t m, size_t n>
void print_2D_arr(T (*arr)[n])
{
for(size_t i = 0; i < m ; ++i)
{
for(size_t j = 0; j < n ; ++j)
cout<<arr[i][j]<<' ';
cout<<endl;
}
}
 
int main(int argc, char* argv[])
{
int a[2][3]={{1,2,3},{4,5,6}};
double b[2][3]={{1.23,2.34,3.45},{4.56,5.67,6.78}};
print_2D_arr<int, 2, 3>(a);
cout<<endl;
print_2D_arr<double, 2, 3>(b);
cout<<endl;
system("pause");
return 0;
}

А вектор векторов чем плох?
Kapex
15 / 15 / 4
Регистрация: 11.11.2014
Сообщений: 121
05.10.2016, 12:14  [ТС]     Передача в поток многомерных массивов по указателю #6
DrOffset, спасибо большое. Попробую. На этапе компиляции, к сожалению, размер не известен, поэтому буду пробовать первый вариант. Но я сейчас вижу бОльшие проблемы в размере данных: хочется натравить несколько потоков на 300 Мб данных (данные хорошо обрабатываются в параллель), причём первоначальная идея был наплодить потоков и каждому потоку отдать кусок: первому -- первые 10 Мб, второму - вторые 10 Мб и т.д. Но при такой организации, чую, потоки уже в L3 будут пузиками толкаться, и я не получу пропорционального выигрыша в скорости обработки данных, ибо всё происходит на одной машине с одним процом и общим кэшем.

IGPIGP, вектор векторов хорош, но я пока не научился просить конструктор вектора аллоцировать данные внутри, выровненные по границе. К тому же я не знаю, как будет вести себя gcc во время оптимизации вектора векторов.
Yandex
Объявления
05.10.2016, 12:14     Передача в поток многомерных массивов по указателю
Ответ Создать тему
Опции темы

Текущее время: 01:02. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru