это нормально для построения из контейнера STL, который имеет другой распределитель?

Скажи у меня

std::vector<T, allocator1=default allocator in STL>  A

std::vector<T, allocator2=some other allocator> B

Я использую __offload :: shared_allocator в качестве allocator2 в Cilk Plus для разгрузки с центрального процессора на сопроцессор Xeon Phi

Могу ли я построить А из Б?

std::vector<T> A{B.begin(), B.end()};

И, в общем, для каких функций STL будут важны разные распределители?

0

Решение

Как отмечено в комментариях, конструктор

std::vector<T> A{B.begin(), B.end()};

должно работать нормально, так как оно работает для любых двух итераторов. Что касается вопроса «для каких функций STL будут важны разные распределители?», Существует два вида «разных»:

  1. Распределители с разными типами.
  2. Распределители одного типа, но сравниваются как разные.

Для несовместимости относительно (1), вы должны увидеть ошибку во время компиляции, потому что система типов поймает ее. Для (2) я не знаю, улавливают ли реализации STL возможные проблемы или нет. Основным контейнером / функцией, о котором следует беспокоиться, являются splice методы на уроке list (а также splice_after методы на уроке forward_list), поскольку они перемещают объект, размещенный в одном контейнере, в другой контейнер. Как отмечается в сноске 265 стандарта C ++ 11, контейнеры STL требуют, чтобы распределители сравнивались одинаково, поэтому такое перемещение не должно быть проблемой.

Что касается проблем разгрузки, если A выделяется с простым распределителем STL, то он не может быть создан на стороне хоста и использован на стороне сопроцессора. Но B можно использовать с обеих сторон. Вот пример, который строит B using anразгружать :: shared_allocator, and constructsОт него на стороне сопроцессора.

#pragma offload_attribute (push, _Cilk_shared)
#include <vector>
#include "offload.h"#include <cstdio>
#pragma offload_attribute (pop)

_Cilk_shared std::vector<int, __offload::shared_allocator<int> > B;

_Cilk_shared void foo() {
#ifdef __MIC__
std::vector<int> A(B.begin(),B.end());
for( auto& x: A )
std::printf("%d\n", x);
#else
std::printf("Host\n");
#endif
}

int main() {
auto y = 1;
for( int i=0; i<10; ++i ) {
B.push_back(y);
y *= 10;
}
_Cilk_offload foo();
}

Следует напечатать:

1
10
100
1000
10000
100000
1000000
10000000
100000000
1000000000
0

Другие решения