diff --git a/.gitlab-ci.common.yml b/.gitlab-ci.common.yml index de3ffcc0b17b568820ddb1f3a886068457d2fa7e..45def8e44f4727400b64422308a26d794307feda 100644 --- a/.gitlab-ci.common.yml +++ b/.gitlab-ci.common.yml @@ -11,6 +11,9 @@ workflow: when: never - when: always +variables: + GIT_SUBMODULE_STRATEGY: recursive + stages: - versioning - prepare diff --git a/.gitmodules b/.gitmodules index d34218b42bd3d311fb017efb5be9083961cb0b7c..58a5a02c14f3370ff3663470518ec6de97c7371a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "external/schaap-packaging"] path = external/schaap-packaging url = https://git.astron.nl/RD/schaap-packaging.git +[submodule "external/aocommon"] + path = external/aocommon + url = https://gitlab.com/aroffringa/aocommon.git diff --git a/CMakeLists.txt b/CMakeLists.txt index a176621e1310c3d1216a5bbdbf54df5857077de4..a8e6fed7edb1d51f71f74e2034f7f193178c09ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,11 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) +include_directories(${CMAKE_SOURCE_DIR}/external/aocommon/include/) +include(external/aocommon/CMake/FetchXTensor.cmake) +include_directories(SYSTEM "${xtensor_SOURCE_DIR}/include") +include_directories(SYSTEM "${xtl_SOURCE_DIR}/include") + # build shared or static libraries (default: shared) if(BUILD_STATIC_LIBS) set(BUILD_SHARED_LIBS FALSE) diff --git a/external/aocommon b/external/aocommon new file mode 160000 index 0000000000000000000000000000000000000000..c9b57adbb537a94a5dd5501697a31fa6bbb26aee --- /dev/null +++ b/external/aocommon @@ -0,0 +1 @@ +Subproject commit c9b57adbb537a94a5dd5501697a31fa6bbb26aee diff --git a/idg-api/BufferSet.cpp b/idg-api/BufferSet.cpp index 9c7b4a78e4635d530a83f0bd231f48ea44c5001f..da15dd8a80e6ca11242ed8bc348d2ebdc78fe9e8 100644 --- a/idg-api/BufferSet.cpp +++ b/idg-api/BufferSet.cpp @@ -76,15 +76,13 @@ BufferSetImpl::BufferSetImpl(Type architecture) m_nr_correlations(4), m_nr_polarizations(4), m_proxy(create_proxy(architecture)), - m_shift(2), + m_shift({0, 0}), m_get_image_watch(Stopwatch::create()), m_set_image_watch(Stopwatch::create()), m_avg_beam_watch(Stopwatch::create()), m_plan_watch(Stopwatch::create()), m_gridding_watch(Stopwatch::create()), - m_degridding_watch(Stopwatch::create()) { - m_shift.zero(); -} + m_degridding_watch(Stopwatch::create()) {} BufferSetImpl::~BufferSetImpl() { // Free all objects allocated via the proxy before destroying the proxy. @@ -258,8 +256,8 @@ void BufferSetImpl::init(size_t size, float cell_size, float max_w, std::cout << "nr_w_layers: " << m_nr_w_layers << std::endl; #endif - m_shift(0) = shiftl; - m_shift(1) = shiftm; + m_shift[0] = shiftl; + m_shift[1] = shiftm; m_kernel_size = taper_kernel_size + w_kernel_size + a_term_kernel_size; diff --git a/idg-api/BufferSetImpl.h b/idg-api/BufferSetImpl.h index eee20a38ce7bc98d8a7a53fcde46650b592d52fe..44190a4d04e1144d33d99c0fb5caff76607c4fa1 100644 --- a/idg-api/BufferSetImpl.h +++ b/idg-api/BufferSetImpl.h @@ -78,7 +78,7 @@ class BufferSetImpl : public virtual BufferSet { float get_cell_size() const { return m_cell_size; } float get_w_step() const { return m_w_step; } - const idg::Array1D<float>& get_shift() const { return m_shift; } + const std::array<float, 2>& get_shift() const { return m_shift; } float get_kernel_size() const { return m_kernel_size; } const Array2D<float>& get_spheroidal() const { return m_spheroidal; } @@ -123,7 +123,7 @@ class BufferSetImpl : public virtual BufferSet { float m_cell_size; float m_w_step; int m_nr_w_layers; - Array1D<float> m_shift; + std::array<float, 2> m_shift; size_t m_size; size_t m_padded_size; float m_kernel_size; diff --git a/idg-api/BulkDegridder.cpp b/idg-api/BulkDegridder.cpp index 1434ccf316576b3927a4cf8bfc93c5a8c34be93f..f37d061c73332ab45d615761524557849481796f 100644 --- a/idg-api/BulkDegridder.cpp +++ b/idg-api/BulkDegridder.cpp @@ -58,19 +58,22 @@ void BulkDegridderImpl::compute_visibilities( static const double kDefaultUVWFactors[3] = {1.0, 1.0, 1.0}; if (!uvw_factors) uvw_factors = kDefaultUVWFactors; - auto bufferStationPairs = - proxy.allocate_array1d<std::pair<unsigned int, unsigned int>>( - nr_baselines); + auto bufferStationPairs_tensor = + proxy.allocate_tensor<std::pair<unsigned int, unsigned int>, 1>( + {nr_baselines}); + auto bufferStationPairs = bufferStationPairs_tensor.Span(); + bufferStationPairs.fill( + std::pair<unsigned int, unsigned int>(nr_stations_, nr_stations_)); std::vector<int> baseline_map; - auto bufferUVW = - proxy.allocate_array2d<UVW<float>>(nr_baselines, nr_timesteps); + auto bufferUVW_tensor = + proxy.allocate_tensor<UVW<float>, 2>({nr_baselines, nr_timesteps}); + auto bufferUVW = bufferUVW_tensor.Span(); auto bufferVisibilities = proxy.allocate_array4d<std::complex<float>>( nr_baselines, nr_timesteps, frequencies_.size(), nr_correlations); // The proxy does not touch visibilities for out-of-bound uvw coordinates. // Since we copy all visibilities to the caller, initialize them to zero. bufferVisibilities.zero(); - bufferStationPairs.init({nr_stations_, nr_stations_}); baseline_map.reserve(nr_baselines); for (size_t bl = 0; bl < nr_baselines; ++bl) { const size_t ant1 = antennas1[bl]; @@ -96,8 +99,10 @@ void BulkDegridderImpl::compute_visibilities( // The proxy expects the number of time steps as last value. std::vector<unsigned int> local_aterm_offsets = aterm_offsets; local_aterm_offsets.push_back(nr_timesteps); - const Array1D<unsigned int> aterm_offsets_array(local_aterm_offsets.data(), - local_aterm_offsets.size()); + const std::array<size_t, 1> local_aterm_offsets_shape{ + local_aterm_offsets.size()}; + auto aterm_offsets_span = aocommon::xt::CreateSpan(local_aterm_offsets.data(), + local_aterm_offsets_shape); // If aterms is empty, create default values and update the pointer. std::vector<Matrix2x2<std::complex<float>>> default_aterms; @@ -113,8 +118,8 @@ void BulkDegridderImpl::compute_visibilities( auto* local_aterms = reinterpret_cast<Matrix2x2<std::complex<float>>*>( const_cast<std::complex<float>*>(aterms)); const Array4D<Matrix2x2<std::complex<float>>> aterms_array( - local_aterms, aterm_offsets_array.get_x_dim() - 1, nr_stations_, - subgridsize, subgridsize); + local_aterms, aterm_offsets_span.size() - 1, nr_stations_, subgridsize, + subgridsize); // Set Plan options Plan::Options options; @@ -126,15 +131,18 @@ void BulkDegridderImpl::compute_visibilities( // Create plan bufferset_.get_watch(BufferSetImpl::Watch::kPlan).Start(); + const std::array<size_t, 1> frequencies_shape{frequencies_.size()}; + auto frequencies_span = + aocommon::xt::CreateSpan(frequencies_.data(), frequencies_shape); std::unique_ptr<Plan> plan = - proxy.make_plan(bufferset_.get_kernel_size(), frequencies_, bufferUVW, - bufferStationPairs, aterm_offsets_array, options); + proxy.make_plan(bufferset_.get_kernel_size(), frequencies_span, bufferUVW, + bufferStationPairs, aterm_offsets_span, options); bufferset_.get_watch(BufferSetImpl::Watch::kPlan).Pause(); // Run degridding bufferset_.get_watch(BufferSetImpl::Watch::kDegridding).Start(); proxy.degridding(*plan, frequencies_, bufferVisibilities, bufferUVW, - bufferStationPairs, aterms_array, aterm_offsets_array, + bufferStationPairs, aterms_array, aterm_offsets_span, bufferset_.get_spheroidal()); bufferset_.get_watch(BufferSetImpl::Watch::kDegridding).Pause(); diff --git a/idg-api/DegridderBuffer.cpp b/idg-api/DegridderBuffer.cpp index 8e09f261923c1f9920cdbd332a492524bb7d12f0..6c4605bfbdc081edafb364d64f9b2529d9f90bdd 100644 --- a/idg-api/DegridderBuffer.cpp +++ b/idg-api/DegridderBuffer.cpp @@ -103,6 +103,10 @@ void DegridderBufferImpl::flush() { m_aterms.data(), m_aterm_offsets_array.get_x_dim() - 1, m_nrStations, subgridsize, subgridsize); + const std::array<size_t, 1> aterm_offsets_shape{m_aterm_offsets_array.size()}; + auto aterm_offsets_span = aocommon::xt::CreateSpan( + m_aterm_offsets_array.data(), aterm_offsets_shape); + proxy::Proxy& proxy = m_bufferset.get_proxy(); // Set Plan options @@ -115,9 +119,18 @@ void DegridderBufferImpl::flush() { // Create plan m_bufferset.get_watch(BufferSetImpl::Watch::kPlan).Start(); + const std::array<size_t, 1> frequencies_shape{m_frequencies.size()}; + auto frequencies_span = + aocommon::xt::CreateSpan(m_frequencies.data(), frequencies_shape); + const std::array<size_t, 1> station_pairs_shape{m_bufferStationPairs.size()}; + const std::array<size_t, 2> uvw_shape{m_bufferUVW.get_y_dim(), + m_bufferUVW.get_x_dim()}; + auto uvw_span = aocommon::xt::CreateSpan(m_bufferUVW.data(), uvw_shape); + auto station_pairs_span = aocommon::xt::CreateSpan( + m_bufferStationPairs.data(), station_pairs_shape); std::unique_ptr<Plan> plan = - proxy.make_plan(m_bufferset.get_kernel_size(), m_frequencies, m_bufferUVW, - m_bufferStationPairs, m_aterm_offsets_array, options); + proxy.make_plan(m_bufferset.get_kernel_size(), frequencies_span, uvw_span, + station_pairs_span, aterm_offsets_span, options); m_bufferset.get_watch(BufferSetImpl::Watch::kPlan).Pause(); // Run degridding diff --git a/idg-api/GridderBuffer.cpp b/idg-api/GridderBuffer.cpp index 084c7c33f83f4383c193e32171c18ac747d50645..b5f7a4cf3f237866c77fdcb3712fa02cdb1bd69f 100644 --- a/idg-api/GridderBuffer.cpp +++ b/idg-api/GridderBuffer.cpp @@ -139,6 +139,10 @@ void GridderBufferImpl::flush_thread_worker() { m_nrStations, subgridsize, subgridsize); } + const std::array<size_t, 1> aterm_offsets_shape{m_aterm_offsets_array.size()}; + auto aterm_offsets_span = aocommon::xt::CreateSpan( + m_aterm_offsets_array.data(), aterm_offsets_shape); + proxy::Proxy& proxy = m_bufferset.get_proxy(); // Set Plan options @@ -151,9 +155,18 @@ void GridderBufferImpl::flush_thread_worker() { // Create plan m_bufferset.get_watch(BufferSetImpl::Watch::kPlan).Start(); - std::unique_ptr<Plan> plan = proxy.make_plan( - m_bufferset.get_kernel_size(), m_frequencies, m_bufferUVW2, - m_bufferStationPairs2, m_aterm_offsets_array, options); + const std::array<size_t, 1> frequencies_shape{m_frequencies.size()}; + auto frequencies_span = + aocommon::xt::CreateSpan(m_frequencies.data(), frequencies_shape); + const std::array<size_t, 1> station_pairs_shape{m_bufferStationPairs.size()}; + const std::array<size_t, 2> uvw_shape{m_bufferUVW2.get_y_dim(), + m_bufferUVW2.get_x_dim()}; + auto uvw_span = aocommon::xt::CreateSpan(m_bufferUVW2.data(), uvw_shape); + auto station_pairs_span = aocommon::xt::CreateSpan( + m_bufferStationPairs2.data(), station_pairs_shape); + std::unique_ptr<Plan> plan = + proxy.make_plan(m_bufferset.get_kernel_size(), frequencies_span, uvw_span, + station_pairs_span, aterm_offsets_span, options); m_bufferset.get_watch(BufferSetImpl::Watch::kPlan).Pause(); // Run gridding diff --git a/idg-bin/CMakeLists.txt b/idg-bin/CMakeLists.txt index 02cd98c066740ec34deacbdaf7c63017c4199ddf..a6f6b380f9a84c46c356c051a23a7706a5334c15 100644 --- a/idg-bin/CMakeLists.txt +++ b/idg-bin/CMakeLists.txt @@ -10,7 +10,6 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) # options option(BUILD_LIB_CPU "Build CPU libraries" ON) option(BUILD_LIB_CUDA "Build CUDA libraries" OFF) -option(USE_DUMMY_VISIBILITIES "Run C++ examples using dummy visibilities" ON) # Compiler settings: if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) diff --git a/idg-bin/examples/cxx/common/common.h b/idg-bin/examples/cxx/common/common.h index 45d06f8d08b68fe723d32955f759ccd1df75057e..c7930899348d3294be8d4f21184e523ca070846a 100644 --- a/idg-bin/examples/cxx/common/common.h +++ b/idg-bin/examples/cxx/common/common.h @@ -15,14 +15,6 @@ #include "idg-cpu.h" #include "idg-util.h" // Data init routines -/* - * Visibilities initializion - * 0, use simulated visibilities for some point sources near the centre of the - * image 1, use fixed (dummy) visibilities to speed-up initialization of the - * data - */ -#define USE_DUMMY_VISIBILITIES 1 - using namespace std; std::tuple<int, int, int, int, int, int, int, int, int, int, int, float, bool, @@ -240,22 +232,22 @@ void run() { // Allocate and initialize static data structures clog << ">>> Initialize data structures" << endl; -#if USE_DUMMY_VISIBILITIES - idg::Array4D<std::complex<float>> visibilities_ = idg::get_dummy_visibilities( - proxy, nr_baselines, nr_timesteps, nr_channels, nr_correlations); -#endif - idg::Array4D<idg::Matrix2x2<std::complex<float>>> aterms = + aocommon::xt::Span<std::complex<float>, 4> visibilities = + idg::get_dummy_visibilities(proxy, nr_baselines, nr_timesteps, + nr_channels, nr_correlations); + aocommon::xt::Span<idg::Matrix2x2<std::complex<float>>, 4> aterms = idg::get_identity_aterms(proxy, nr_timeslots, nr_stations, subgrid_size, subgrid_size); - idg::Array1D<unsigned int> aterm_offsets = + aocommon::xt::Span<unsigned int, 1> aterm_offsets = idg::get_example_aterm_offsets(proxy, nr_timeslots, nr_timesteps); - idg::Array2D<float> spheroidal = + aocommon::xt::Span<float, 2> spheroidal = idg::get_example_spheroidal(proxy, subgrid_size, subgrid_size); + auto grid = proxy.allocate_grid(nr_w_layers, nr_polarizations, grid_size, grid_size); grid->zero(); - idg::Array1D<float> shift = idg::get_zero_shift(); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines = + std::array<float, 2> shift{0.0f, 0.0f}; + aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1> baselines = idg::get_example_baselines(proxy, nr_stations, nr_baselines); clog << endl; @@ -272,13 +264,9 @@ void run() { bool disable_degridding = getenv("DISABLE_DEGRIDDING"); bool disable_fft = getenv("DISABLE_FFT"); - // Spectral line imaging - bool simulate_spectral_line = getenv("SPECTRAL_LINE"); - // Plan options idg::Plan::Options options; options.plan_strict = true; - options.simulate_spectral_line = simulate_spectral_line; options.max_nr_timesteps_per_subgrid = 128; options.max_nr_channels_per_subgrid = 8; options.mode = stokes_i_only ? idg::Plan::Mode::STOKES_I_ONLY @@ -304,13 +292,16 @@ void run() { std::ceil((float)total_nr_timesteps / nr_timesteps); for (unsigned int t = 0; t < nr_time_blocks; t++) { int time_offset = t * nr_timesteps; - int current_nr_timesteps = total_nr_timesteps - time_offset < nr_timesteps - ? total_nr_timesteps - time_offset - : nr_timesteps; + const size_t current_nr_timesteps = + total_nr_timesteps - time_offset < nr_timesteps + ? total_nr_timesteps - time_offset + : nr_timesteps; // Initalize UVW coordiantes - auto uvw = proxy.allocate_array2d<idg::UVW<float>>(nr_baselines, - current_nr_timesteps); + aocommon::xt::Span<idg::UVW<float>, 2> uvw = + proxy.allocate_span<idg::UVW<float>, 2>( + {nr_baselines, current_nr_timesteps}); + data.get_uvw(uvw, 0, time_offset, integration_time); // Iterate all channel blocks @@ -325,22 +316,10 @@ void run() { clog << ">>>" << endl; // Initialize frequency data - idg::Array1D<float> frequencies = - proxy.allocate_array1d<float>(nr_channels); + aocommon::xt::Span<float, 1> frequencies = + proxy.allocate_span<float, 1>({nr_channels}); data.get_frequencies(frequencies, image_size, channel_offset); -// Initialize visibilities -#if !USE_DUMMY_VISIBILITIES - idg::Array4D<std::complex<float>> visibilities_ = - idg::get_example_visibilities(proxy, uvw, frequencies, image_size, - grid_size, nr_correlations); -#endif - - auto nr_channels_ = simulate_spectral_line ? 1 : nr_channels; - idg::Array4D<std::complex<float>> visibilities( - visibilities_.data(), nr_baselines, current_nr_timesteps, - nr_channels_, nr_correlations); - // Create plan if (plans.size() == 0 || cycle == 0) { plans.emplace_back(proxy.make_plan(kernel_size, frequencies, uvw, diff --git a/idg-bin/examples/cxx/distributed/common/common.h b/idg-bin/examples/cxx/distributed/common/common.h index adf720acc2d6c320fe95e03dea407ae0f326e0d3..8df1c479f56c4c57dacca9107e594b913fdb56e4 100644 --- a/idg-bin/examples/cxx/distributed/common/common.h +++ b/idg-bin/examples/cxx/distributed/common/common.h @@ -147,14 +147,15 @@ float receive_float(int src = 0) { } template <typename T> -void send_array(int dst, T& array) { - MPI_Send(array.data(), array.bytes(), MPI_BYTE, dst, 0, MPI_COMM_WORLD); +void send_tensor(int dst, T& tensor) { + MPI_Send(tensor.data(), tensor.size() * sizeof(T), MPI_BYTE, dst, 0, + MPI_COMM_WORLD); } template <typename T> -void receive_array(int src, T& array) { - MPI_Recv(array.data(), array.bytes(), MPI_BYTE, src, 0, MPI_COMM_WORLD, - MPI_STATUS_IGNORE); +void receive_tensor(int src, T& tensor) { + MPI_Recv(tensor.data(), tensor.size() * sizeof(T), MPI_BYTE, src, 0, + MPI_COMM_WORLD, MPI_STATUS_IGNORE); } void send_bytes(int dst, void* buf, size_t bytes) { @@ -249,7 +250,7 @@ void reduce_grids(std::shared_ptr<idg::Grid> grid, unsigned int rank, unsigned int nr_polarizations = grid->get_z_dim(); unsigned int grid_size = grid->get_y_dim(); - idg::Array2D<std::complex<float>> tmp(grid_size, grid_size); + xt::xtensor<std::complex<float>, 2> tmp({grid_size, grid_size}); size_t sizeof_row = grid_size * sizeof(std::complex<float>); #pragma omp parallel @@ -260,7 +261,7 @@ void reduce_grids(std::shared_ptr<idg::Grid> grid, unsigned int rank, if (omp_get_thread_num() == 0) { MPIRequestList requests; for (unsigned int y = 0; y < grid_size; y++) { - requests.create()->receive(tmp.data(y, 0), sizeof_row, i + rank); + requests.create()->receive(&tmp(y, 0), sizeof_row, i + rank); } requests.wait(); } @@ -271,12 +272,12 @@ void reduce_grids(std::shared_ptr<idg::Grid> grid, unsigned int rank, #pragma omp for for (unsigned int y = 0; y < grid_size; y++) for (unsigned int x = 0; x < grid_size; x++) { - grid_(w, pol, y, x) += *tmp.data(y, x); + grid_(w, pol, y, x) += tmp(y, x); } } else if (rank < (2 * i) && omp_get_thread_num() == 0) { MPIRequestList requests; for (unsigned int y = 0; y < grid_size; y++) { - requests.create()->send(tmp.data(y, 0), sizeof_row, rank - i); + requests.create()->send(&tmp(y, 0), sizeof_row, rank - i); } } } // end for i @@ -383,8 +384,12 @@ void run_master() { send_string(dst, layout_file); } + // Initialize proxy + ProxyType proxy; + // Initialize frequency data for master - idg::Array1D<float> frequencies(nr_channels); + aocommon::xt::Span<float, 1> frequencies = + proxy.allocate_span<float, 1>({nr_channels}); data.get_frequencies(frequencies, image_size); // Distribute frequencies to workers @@ -392,10 +397,11 @@ void run_master() { // take a channel offset into account when initializing // frequencies. for (int dst = 1; dst < world_size; dst++) { - int channel_offset = (dst - 1) * nr_channels; - idg::Array1D<float> frequencies_(nr_channels); + const int channel_offset = (dst - 1) * nr_channels; + aocommon::xt::Span<float, 1> frequencies_ = + proxy.allocate_span<float, 1>({nr_channels}); data.get_frequencies(frequencies_, image_size, channel_offset); - send_array(dst, frequencies_); + send_tensor(dst, frequencies_); } // Distribute data @@ -403,21 +409,18 @@ void run_master() { send_bytes(dst, &data, sizeof(data)); } - // Initialize proxy - ProxyType proxy; - // Allocate and initialize static data structures - idg::Array4D<idg::Matrix2x2<std::complex<float>>> aterms = + aocommon::xt::Span<idg::Matrix2x2<std::complex<float>>, 4> aterms = idg::get_identity_aterms(proxy, nr_timeslots, nr_stations, subgrid_size, subgrid_size); - idg::Array1D<unsigned int> aterm_offsets = + aocommon::xt::Span<unsigned int, 1> aterm_offsets = idg::get_example_aterm_offsets(proxy, nr_timeslots, nr_timesteps); - idg::Array2D<float> spheroidal = + aocommon::xt::Span<float, 2> spheroidal = idg::get_example_spheroidal(proxy, subgrid_size, subgrid_size); - auto grid = + std::shared_ptr<idg::Grid> grid = proxy.allocate_grid(nr_w_layers, nr_correlations, grid_size, grid_size); - idg::Array1D<float> shift = idg::get_zero_shift(); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines = + std::array<float, 2> shift{0.0f, 0.0f}; + aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1> baselines = idg::get_example_baselines(proxy, nr_stations, nr_baselines); // Plan options @@ -427,10 +430,12 @@ void run_master() { // Buffers for input data unsigned int nr_time_blocks = std::ceil((float)total_nr_timesteps / nr_timesteps); - idg::Array3D<idg::UVW<float>> uvws = proxy.allocate_array3d<idg::UVW<float>>( - nr_time_blocks, nr_baselines, nr_timesteps); - idg::Array4D<std::complex<float>> visibilities = idg::get_dummy_visibilities( - proxy, nr_baselines, nr_timesteps, nr_channels, nr_correlations); + aocommon::xt::Span<idg::UVW<float>, 3> uvws = + proxy.allocate_span<idg::UVW<float>, 3>( + {nr_time_blocks, nr_baselines, nr_timesteps}); + aocommon::xt::Span<std::complex<float>, 4> visibilities = + idg::get_dummy_visibilities(proxy, nr_baselines, nr_timesteps, + nr_channels, nr_correlations); unsigned int bl_offset = 0; // Vector of plans @@ -491,8 +496,9 @@ void run_master() { unsigned int time_offset = t * nr_timesteps; // Get UVW coordinates for current cycle - idg::Array2D<idg::UVW<float>> uvw(uvws.data(t, 0, 0), nr_baselines, - nr_timesteps); + const std::array<size_t, 2> uvw_shape{nr_baselines, nr_timesteps}; + auto uvw = aocommon::xt::CreateSpan(&uvws(t, 0, 0), uvw_shape); + if (init) { runtimes_init[t] -= omp_get_wtime(); data.get_uvw(uvw, bl_offset, time_offset, integration_time); @@ -638,22 +644,23 @@ void run_worker() { ProxyType proxy; // Allocate and initialize static data structures - idg::Array4D<idg::Matrix2x2<std::complex<float>>> aterms = + aocommon::xt::Span<idg::Matrix2x2<std::complex<float>>, 4> aterms = idg::get_identity_aterms(proxy, nr_timeslots, nr_stations, subgrid_size, subgrid_size); - idg::Array1D<unsigned int> aterm_offsets = + aocommon::xt::Span<unsigned int, 1> aterm_offsets = idg::get_example_aterm_offsets(proxy, nr_timeslots, nr_timesteps); - idg::Array2D<float> spheroidal = + aocommon::xt::Span<float, 2> spheroidal = idg::get_example_spheroidal(proxy, subgrid_size, subgrid_size); - auto grid = + std::shared_ptr<idg::Grid> grid = proxy.allocate_grid(nr_w_layers, nr_correlations, grid_size, grid_size); - idg::Array1D<float> shift = idg::get_zero_shift(); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines = + std::array<float, 2> shift{0.0f, 0.0f}; + aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1> baselines = idg::get_example_baselines(proxy, nr_stations, nr_baselines); // Receive frequencies - idg::Array1D<float> frequencies = proxy.allocate_array1d<float>(nr_channels); - receive_array(0, frequencies); + aocommon::xt::Span<float, 1> frequencies = + proxy.allocate_span<float, 1>({nr_channels}); + receive_tensor(0, frequencies); // Receive data idg::Data data = @@ -667,10 +674,12 @@ void run_worker() { // Buffers for input data unsigned int nr_time_blocks = std::ceil((float)total_nr_timesteps / nr_timesteps); - idg::Array3D<idg::UVW<float>> uvws = proxy.allocate_array3d<idg::UVW<float>>( - nr_time_blocks, nr_baselines, nr_timesteps); - idg::Array4D<std::complex<float>> visibilities = idg::get_dummy_visibilities( - proxy, nr_baselines, nr_timesteps, nr_channels, nr_correlations); + aocommon::xt::Span<idg::UVW<float>, 3> uvws = + proxy.allocate_span<idg::UVW<float>, 3>( + {nr_time_blocks, nr_baselines, nr_timesteps}); + aocommon::xt::Span<std::complex<float>, 4> visibilities = + idg::get_dummy_visibilities(proxy, nr_baselines, nr_timesteps, + nr_channels, nr_correlations); unsigned int bl_offset = 0; // Vector of plans @@ -710,8 +719,10 @@ void run_worker() { unsigned int time_offset = t * nr_timesteps; // Get UVW coordinates for current cycle - idg::Array2D<idg::UVW<float>> uvw(uvws.data(t, 0, 0), nr_baselines, - nr_timesteps); + const std::array<size_t, 2> uvw_shape{nr_baselines, nr_timesteps}; + aocommon::xt::Span<idg::UVW<float>, 2> uvw = + aocommon::xt::CreateSpan(&uvws(t, 0, 0), uvw_shape); + if (init) { data.get_uvw(uvw, bl_offset, time_offset, integration_time); } diff --git a/idg-bin/examples/cxx/plan/main.cpp b/idg-bin/examples/cxx/plan/main.cpp index fd788d6d156b81e6140d6f9c602fc338509bfcec..352e560a7163aa617c3e2e652ab836e97c71a8fa 100644 --- a/idg-bin/examples/cxx/plan/main.cpp +++ b/idg-bin/examples/cxx/plan/main.cpp @@ -163,22 +163,9 @@ int main(int argc, char** argv) { std::clog << ">>> Initialize data structures" << std::endl; // Initialize shift - idg::Array1D<float> shift = idg::get_zero_shift(); - - // Initialize frequency data - idg::Array1D<float> frequencies(nr_channels); - data.get_frequencies(frequencies, image_size); - - // Initalize UVW coordiantes - idg::Array2D<idg::UVW<float>> uvw(nr_baselines, nr_timesteps); - data.get_uvw(uvw); - - // Initialize metadata - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines = - idg::get_example_baselines(nr_stations, nr_baselines); - idg::Array1D<unsigned int> aterm_offsets = - idg::get_example_aterm_offsets(nr_timeslots, nr_timesteps); + std::array<float, 2> shift{0.0f, 0.0f}; + // Initialize proxy unsigned int nr_correlations = 4; idg::proxy::cpu::Optimized proxy; std::shared_ptr<idg::Grid> grid( @@ -188,6 +175,21 @@ int main(int argc, char** argv) { proxy.init_cache(subgrid_size, cell_size, w_step, shift); + // Initalize UVW coordinates + aocommon::xt::Span<idg::UVW<float>, 2> uvw = + proxy.allocate_span<idg::UVW<float>, 2>({nr_baselines, nr_timesteps}); + data.get_uvw(uvw); + + // Initialize frequency data + auto frequencies = proxy.allocate_span<float, 1>({nr_channels}); + data.get_frequencies(frequencies, image_size); + + // Initialize metadata + aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1> baselines = + idg::get_example_baselines(proxy, nr_stations, nr_baselines); + aocommon::xt::Span<unsigned int, 1> aterm_offsets = + idg::get_example_aterm_offsets(proxy, nr_timeslots, nr_timesteps); + // Create plan std::clog << ">>> Create plan" << std::endl; idg::Plan::Options options; diff --git a/idg-bin/tests/cxx/CPU/Reference/main.cpp b/idg-bin/tests/cxx/CPU/Reference/main.cpp index c6bb03134459c1d620ca2d0542f20402a47c45f3..ab9d26efafa0b3f29f66867dd51d7c486f5fdcf9 100644 --- a/idg-bin/tests/cxx/CPU/Reference/main.cpp +++ b/idg-bin/tests/cxx/CPU/Reference/main.cpp @@ -1,6 +1,8 @@ // Copyright (C) 2020 ASTRON (Netherlands Institute for Radio Astronomy) // SPDX-License-Identifier: GPL-3.0-or-later +#include <xtensor/xcomplex.hpp> + #include "idg-cpu.h" // Reference proxy #include "idg-util.h" // Data init routines @@ -50,31 +52,39 @@ int test01() { // error tolerance, which might need to be adjusted if parameters are changed float tol = 0.1f; + // Initialize proxy + clog << ">>> Initialize proxy" << endl; + idg::proxy::cpu::Reference proxy; + + // Initialize frequency data + aocommon::xt::Span<float, 1> frequencies = + proxy.allocate_span<float, 1>({nr_channels}); + data.get_frequencies(frequencies, image_size); + // Allocate and initialize data structures clog << ">>> Initialize data structures" << endl; - idg::Array1D<float> frequencies(nr_channels); - data.get_frequencies(frequencies, image_size); - idg::Array2D<idg::UVW<float>> uvw = data.get_uvw(nr_baselines, nr_timesteps); - idg::Array4D<std::complex<float>> visibilities = - idg::get_example_visibilities(uvw, frequencies, image_size, grid_size, - nr_correlations); - idg::Array4D<std::complex<float>> visibilities_ref = - idg::get_example_visibilities(uvw, frequencies, image_size, grid_size, - nr_correlations); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines = - idg::get_example_baselines(nr_stations, nr_baselines); + auto uvw = + proxy.allocate_span<idg::UVW<float>, 2>({nr_baselines, nr_timesteps}); + aocommon::xt::Span<std::complex<float>, 4> visibilities = + idg::get_example_visibilities(proxy, uvw, frequencies, image_size, + nr_correlations, grid_size); + aocommon::xt::Span<std::complex<float>, 4> visibilities_ref = + idg::get_example_visibilities(proxy, uvw, frequencies, image_size, + nr_correlations, grid_size); + aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1> baselines = + idg::get_example_baselines(proxy, nr_stations, nr_baselines); auto grid = std::make_shared<idg::Grid>(nr_w_layers, nr_correlations, grid_size, grid_size); auto grid_ref = std::make_shared<idg::Grid>(nr_w_layers, nr_correlations, grid_size, grid_size); - idg::Array4D<idg::Matrix2x2<std::complex<float>>> aterms = - idg::get_identity_aterms(nr_timeslots, nr_stations, subgrid_size, + aocommon::xt::Span<idg::Matrix2x2<std::complex<float>>, 4> aterms = + idg::get_identity_aterms(proxy, nr_timeslots, nr_stations, subgrid_size, subgrid_size); - idg::Array1D<unsigned int> aterm_offsets = - idg::get_example_aterm_offsets(nr_timeslots, nr_timesteps); - idg::Array2D<float> spheroidal = - idg::get_identity_spheroidal(subgrid_size, subgrid_size); - idg::Array1D<float> shift = idg::get_zero_shift(); + aocommon::xt::Span<unsigned int, 1> aterm_offsets = + idg::get_example_aterm_offsets(proxy, nr_timeslots, nr_timesteps); + aocommon::xt::Span<float, 2> spheroidal = + idg::get_identity_spheroidal(proxy, subgrid_size, subgrid_size); + std::array<float, 2> shift{0.0f, 0.0f}; clog << endl; // Set w-terms to zero @@ -96,15 +106,11 @@ int test01() { (*grid_ref)(0, 1, location_y, location_x) = amplitude; (*grid_ref)(0, 2, location_y, location_x) = amplitude; (*grid_ref)(0, 3, location_y, location_x) = amplitude; - visibilities_ref.zero(); + visibilities_ref.fill(std::complex<float>(0.0f, 0.0f)); add_pt_src(visibilities_ref, uvw, frequencies, image_size, grid_size, offset_x, offset_y, amplitude); clog << endl; - // Initialize proxy - clog << ">>> Initialize proxy" << endl; - idg::proxy::cpu::Reference proxy; - // Set grid proxy.set_grid(grid); float w_step = 0.0; diff --git a/idg-bin/tests/cxx/CUDA/wtiling/backward.cpp b/idg-bin/tests/cxx/CUDA/wtiling/backward.cpp index 25eec893c8476f94d6c04cced289651d5be92337..ad8957444d40d61c6abf2e95c8e5b7aa9aedf866 100644 --- a/idg-bin/tests/cxx/CUDA/wtiling/backward.cpp +++ b/idg-bin/tests/cxx/CUDA/wtiling/backward.cpp @@ -141,7 +141,8 @@ void subgrids_from_wtiles(const long nr_subgrids, const int nr_polarizations, void wtiles_from_grid(int nr_tiles, int nr_polarizations, int grid_size, int tile_size, int padded_tile_size, int* tile_ids, idg::Coordinate* tile_coordinates, - std::complex<float>* tiles, std::complex<float>* grid) { + xt::xtensor<std::complex<float>, 4>& tiles, + std::complex<float>* grid) { // Extract tiles from grid for (int i = 0; i < nr_tiles; i++) { idg::Coordinate& coordinate = tile_coordinates[i]; @@ -161,12 +162,8 @@ void wtiles_from_grid(int nr_tiles, int nr_polarizations, int grid_size, for (int pol = 0; pol < nr_polarizations; pol++) { const int index_pol_transposed[4] = {0, 2, 1, 3}; unsigned int pol_src = index_pol_transposed[pol]; - unsigned int pol_dst = pol; unsigned long src_idx = index_grid_3d(grid_size, pol_src, y, x); - unsigned long dst_idx = - index_grid_4d(nr_polarizations, padded_tile_size, i, pol_dst, - (y - y0), (x - x0)); - tiles[dst_idx] = grid[src_idx]; + tiles(i, pol, y - y0, x - x0) = grid[src_idx]; } } } @@ -200,17 +197,22 @@ int main(int argc, char* argv[]) { float cell_size = image_size / grid_size; // Initialize data - idg::Array1D<float> frequencies(nr_channels); - data.get_frequencies(frequencies, image_size); - idg::Array2D<idg::UVW<float>> uvw(nr_baselines, nr_timesteps); - data.get_uvw(uvw); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines = + const std::array<size_t, 1> frequencies_shape{nr_channels}; + xt::xtensor<float, 1> frequencies(frequencies_shape); + aocommon::xt::Span<float, 1> frequencies_span = + aocommon::xt::CreateSpan(frequencies); + data.get_frequencies(frequencies_span, image_size); + const std::array<size_t, 2> uvw_shape{nr_baselines, nr_timesteps}; + xt::xtensor<idg::UVW<float>, 2> uvw(uvw_shape); + auto uvw_span = aocommon::xt::CreateSpan(uvw); + data.get_uvw(uvw_span); + xt::xtensor<std::pair<unsigned int, unsigned int>, 1> baselines = idg::get_example_baselines(nr_stations, nr_baselines); - idg::Array1D<unsigned int> aterm_offsets = - idg::get_example_aterm_offsets(nr_timeslots, nr_timesteps); - idg::Array1D<float> shift = idg::get_zero_shift(); - shift(0) = 10.1f; - shift(0) = 20.2f; + auto baselines_span = aocommon::xt::CreateSpan(baselines); + xt::xtensor<unsigned int, 1> aterm_offsets({nr_timeslots + 1}, 0); + auto aterm_offsets_span = aocommon::xt::CreateSpan(aterm_offsets); + idg::init_example_aterm_offsets(aterm_offsets_span, nr_timesteps); + std::array<float, 2> shift{10.1f, 20.2f}; // Set w-terms to zero for (unsigned bl = 0; bl < nr_baselines; bl++) { @@ -224,7 +226,8 @@ int main(int argc, char* argv[]) { idg::Plan::Options options; options.plan_strict = true; idg::Plan plan(kernel_size, subgrid_size, grid_size, cell_size, shift, - frequencies, uvw, baselines, aterm_offsets, wtiles, options); + frequencies_span, uvw_span, baselines_span, aterm_offsets_span, + wtiles, options); int nr_subgrids = plan.get_nr_subgrids(); // Get W-Tiling paramters @@ -305,7 +308,7 @@ int main(int argc, char* argv[]) { h_tiles.size()); // Init shift - stream.memcpyHtoDAsync(d_shift, shift.data(), shift.bytes()); + stream.memcpyHtoDAsync(d_shift, shift.data(), sizeof_shift); // Start tests std::cout << std::endl; @@ -369,13 +372,13 @@ int main(int argc, char* argv[]) { stream.synchronize(); // Run splitter_wtiles_from_grid on host - idg::Array4D<std::complex<float>> padded_tiles( - max_nr_tiles, nr_polarizations, padded_tile_size, padded_tile_size); - padded_tiles.zero(); + xt::xtensor<std::complex<float>, 4> padded_tiles( + {max_nr_tiles, nr_polarizations, padded_tile_size, padded_tile_size}, + std::complex<float>(0.0f, 0.0f)); wtiles_from_grid(nr_tiles, nr_polarizations, grid_size, tile_size - subgrid_size, padded_tile_size, static_cast<int*>(h_padded_tile_ids.data()), - tile_coordinates.data(), padded_tiles.data(), + tile_coordinates.data(), padded_tiles, static_cast<std::complex<float>*>(u_grid.data())); n = nr_tiles * nr_polarizations * padded_tile_size * padded_tile_size; diff --git a/idg-bin/tests/cxx/CUDA/wtiling/forward.cpp b/idg-bin/tests/cxx/CUDA/wtiling/forward.cpp index 9433eef08f5e3975ec31f693ae75cc94e54e9c8a..095203d509436f2a3191eafec9bfacfc4b93f709 100644 --- a/idg-bin/tests/cxx/CUDA/wtiling/forward.cpp +++ b/idg-bin/tests/cxx/CUDA/wtiling/forward.cpp @@ -217,7 +217,8 @@ void subgrids_to_wtiles(const long nr_subgrids, const int nr_polarizations, void wtiles_to_grid(int nr_tiles, int nr_polarizations, int grid_size, int tile_size, int padded_tile_size, int* tile_ids, idg::Coordinate* tile_coordinates, - std::complex<float>* tiles, std::complex<float>* grid) { + std::complex<float>* tiles, + xt::xtensor<std::complex<float>, 3>& grid) { for (int i = 0; i < nr_tiles; i++) { idg::Coordinate& coordinate = tile_coordinates[i]; @@ -236,11 +237,10 @@ void wtiles_to_grid(int nr_tiles, int nr_polarizations, int grid_size, const int index_pol_transposed[nr_polarizations] = {0, 2, 1, 3}; unsigned int pol_src = pol; unsigned int pol_dst = index_pol_transposed[pol]; - unsigned long dst_idx = index_grid_3d(grid_size, pol_src, y, x); unsigned long src_idx = index_grid_4d(nr_polarizations, padded_tile_size, i, pol_dst, (y - y0), (x - x0)); - grid[dst_idx] += tiles[src_idx]; + grid(pol_src, y, x) += tiles[src_idx]; } // end for pol } // end for x } // end for y @@ -274,17 +274,21 @@ int main(int argc, char* argv[]) { float w_step = 4.0 / (image_size * image_size); // Initialize data - idg::Array1D<float> frequencies(nr_channels); - data.get_frequencies(frequencies, image_size); - idg::Array2D<idg::UVW<float>> uvw(nr_baselines, nr_timesteps); - data.get_uvw(uvw); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines = + const std::array<size_t, 1> frequencies_shape{nr_channels}; + xt::xtensor<float, 1> frequencies(frequencies_shape); + aocommon::xt::Span<float, 1> frequencies_span = + aocommon::xt::CreateSpan(frequencies); + data.get_frequencies(frequencies_span, image_size); + const std::array<size_t, 2> uvw_shape{nr_baselines, nr_timesteps}; + xt::xtensor<idg::UVW<float>, 2> uvw(uvw_shape); + auto uvw_span = aocommon::xt::CreateSpan(uvw); + data.get_uvw(uvw_span); + xt::xtensor<std::pair<unsigned int, unsigned int>, 1> baselines = idg::get_example_baselines(nr_stations, nr_baselines); - idg::Array1D<unsigned int> aterm_offsets = - idg::get_example_aterm_offsets(nr_timeslots, nr_timesteps); - idg::Array1D<float> shift = idg::get_zero_shift(); - shift(0) = 10.1f; - shift(0) = 20.2f; + auto baselines_span = aocommon::xt::CreateSpan(baselines); + xt::xtensor<unsigned int, 1> aterm_offsets({nr_timeslots + 1}, 0); + auto aterm_offsets_span = aocommon::xt::CreateSpan(aterm_offsets); + std::array<float, 2> shift{10.1f, 20.2f}; // Set w-terms to zero for (unsigned bl = 0; bl < nr_baselines; bl++) { @@ -298,7 +302,8 @@ int main(int argc, char* argv[]) { idg::Plan::Options options; options.plan_strict = true; idg::Plan plan(kernel_size, subgrid_size, grid_size, cell_size, shift, - frequencies, uvw, baselines, aterm_offsets, wtiles, options); + frequencies_span, uvw_span, baselines_span, aterm_offsets_span, + wtiles, options); int nr_subgrids = plan.get_nr_subgrids(); // Get W-Tiling paramters @@ -379,7 +384,7 @@ int main(int argc, char* argv[]) { h_tiles.size()); // Init shift - stream.memcpyHtoDAsync(d_shift, shift.data(), shift.bytes()); + stream.memcpyHtoDAsync(d_shift, shift.data(), sizeof_shift); // Start tests std::cout << std::endl; @@ -549,14 +554,14 @@ int main(int argc, char* argv[]) { stream.synchronize(); // Run adder_wtiles_to_grid on host - idg::Array3D<std::complex<float>> grid(nr_polarizations, grid_size, - grid_size); - grid.zero(); + xt::xtensor<std::complex<float>, 3> grid( + {nr_polarizations, grid_size, grid_size}, + std::complex<float>(0.0f, 0.0f)); wtiles_to_grid( nr_tiles, nr_polarizations, grid_size, tile_size - subgrid_size, padded_tile_size, static_cast<int*>(h_padded_tile_ids.data()), tile_coordinates.data(), - static_cast<std::complex<float>*>(h_padded_tiles.data()), grid.data()); + static_cast<std::complex<float>*>(h_padded_tiles.data()), grid); n = nr_polarizations * grid_size * grid_size; accuracy = compare_arrays(n, static_cast<std::complex<float>*>(u_grid.data()), @@ -632,12 +637,12 @@ int main(int argc, char* argv[]) { } // Create reference grid - grid.zero(); + grid.fill(std::complex<float>(0.0f, 0.0f)); wtiles_to_grid( nr_tiles, nr_polarizations, grid_size, tile_size - subgrid_size, padded_tile_size, static_cast<int*>(h_padded_tile_ids.data()), tile_coordinates.data(), - static_cast<std::complex<float>*>(h_padded_tiles.data()), grid.data()); + static_cast<std::complex<float>*>(h_padded_tiles.data()), grid); n = nr_polarizations * grid_size * grid_size; accuracy = compare_arrays(n, static_cast<std::complex<float>*>(u_grid.data()), diff --git a/idg-bin/tests/cxx/common/common.cpp b/idg-bin/tests/cxx/common/common.cpp index 87d301098d6e5ffeb9e0757addcf7b2b1073b695..28f9187c570e87412779e212507fc0791fffbed1 100644 --- a/idg-bin/tests/cxx/common/common.cpp +++ b/idg-bin/tests/cxx/common/common.cpp @@ -145,30 +145,30 @@ int compare(idg::proxy::Proxy& proxy1, idg::proxy::Proxy& proxy2, float tol) { image_size, grid_size, subgrid_size, kernel_size); std::clog << ">>> Initialize data structures" << std::endl; - idg::Array1D<float> frequencies = proxy2.allocate_array1d<float>(nr_channels); - + aocommon::xt::Span<float, 1> frequencies = + proxy2.allocate_span<float, 1>({nr_channels}); data.get_frequencies(frequencies, image_size); - idg::Array2D<idg::UVW<float>> uvw = - proxy2.allocate_array2d<idg::UVW<float>>(nr_baselines, nr_timesteps); + aocommon::xt::Span<idg::UVW<float>, 2> uvw = + proxy2.allocate_span<idg::UVW<float>, 2>({nr_baselines, nr_timesteps}); data.get_uvw(uvw); - idg::Array4D<std::complex<float>> visibilities = idg::get_dummy_visibilities( - proxy2, nr_baselines, nr_timesteps, nr_channels, nr_correlations); - idg::Array4D<std::complex<float>> visibilities_ref = + aocommon::xt::Span<std::complex<float>, 4> visibilities = + idg::get_dummy_visibilities(proxy2, nr_baselines, nr_timesteps, + nr_channels, nr_correlations); + aocommon::xt::Span<std::complex<float>, 4> visibilities_ref = idg::get_dummy_visibilities(proxy1, nr_baselines, nr_timesteps, nr_channels, nr_correlations); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines = + aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1> baselines = idg::get_example_baselines(proxy2, nr_stations, nr_baselines); - idg::Array4D<idg::Matrix2x2<std::complex<float>>> aterms = + aocommon::xt::Span<idg::Matrix2x2<std::complex<float>>, 4> aterms = idg::get_example_aterms(proxy2, nr_timeslots, nr_stations, subgrid_size, subgrid_size); - idg::Array1D<unsigned int> aterm_offsets = + aocommon::xt::Span<unsigned int, 1> aterm_offsets = idg::get_example_aterm_offsets(proxy2, nr_timeslots, nr_timesteps); - idg::Array2D<float> spheroidal = + aocommon::xt::Span<float, 2> spheroidal = idg::get_example_spheroidal(proxy2, subgrid_size, subgrid_size); - idg::Array1D<float> shift = idg::get_zero_shift(); // Set shift to some random non-zero value - shift(0) = 0.02; // shift is in radians, 0.02rad is about 1deg - shift(1) = -0.03; + // shift is in radians, 0.02rad is about 1deg + std::array<float, 2> shift{0.02f, -0.03f}; auto grid = proxy2.allocate_grid(1, nr_polarizations, grid_size, grid_size); auto grid_ref = proxy1.allocate_grid(1, nr_polarizations, grid_size, grid_size); @@ -237,12 +237,12 @@ int compare(idg::proxy::Proxy& proxy1, idg::proxy::Proxy& proxy2, float tol) { #if TEST_DEGRIDDING // Run degridder std::clog << ">>> Run degridding" << std::endl; - visibilities.zero(); + visibilities.fill(std::complex<float>(0.0f, 0.0f)); proxy2.degridding(*plan2, frequencies, visibilities, uvw, baselines, aterms, aterm_offsets, spheroidal); std::clog << ">>> Run reference degridding" << std::endl; - visibilities_ref.zero(); + visibilities_ref.fill(std::complex<float>(0.0f, 0.0f)); proxy1.degridding(*plan1, frequencies, visibilities_ref, uvw, baselines, aterms, aterm_offsets, spheroidal); diff --git a/idg-lib/src/CPU/common/CPU.cpp b/idg-lib/src/CPU/common/CPU.cpp index b9f9c1afdf3e6e75a537e06667a3326f288c5f08..ef527a248f1cc9bfd32c3cf2908cfa017b87b260 100644 --- a/idg-lib/src/CPU/common/CPU.cpp +++ b/idg-lib/src/CPU/common/CPU.cpp @@ -43,10 +43,12 @@ std::unique_ptr<auxiliary::Memory> CPU::allocate_memory(size_t bytes) { } std::unique_ptr<Plan> CPU::make_plan( - const int kernel_size, const Array1D<float>& frequencies, - const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, Plan::Options options) { + const int kernel_size, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, + Plan::Options options) { if (supports_wtiling() && m_cache_state.w_step != 0.0 && m_wtiles.get_wtile_buffer_size()) { options.w_step = m_cache_state.w_step; @@ -62,7 +64,7 @@ std::unique_ptr<Plan> CPU::make_plan( } void CPU::init_cache(int subgrid_size, float cell_size, float w_step, - const Array1D<float>& shift) { + const std::array<float, 2>& shift) { Proxy::init_cache(subgrid_size, cell_size, w_step, shift); const int nr_polarizations = m_grid->get_z_dim(); const size_t grid_size = m_grid->get_x_dim(); diff --git a/idg-lib/src/CPU/common/CPU.h b/idg-lib/src/CPU/common/CPU.h index ccf293575cda46a1888d9aaa7c56f881b27b6da4..1207e51a2dec5ca9f1dd676aa0cc613c15ba91e9 100644 --- a/idg-lib/src/CPU/common/CPU.h +++ b/idg-lib/src/CPU/common/CPU.h @@ -37,14 +37,15 @@ class CPU : public Proxy { std::shared_ptr<kernel::cpu::InstanceCPU> get_kernels() { return m_kernels; } std::unique_ptr<Plan> make_plan( - const int kernel_size, const Array1D<float>& frequencies, - const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, + const int kernel_size, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, Plan::Options options) override; void init_cache(int subgrid_size, float cell_size, float w_step, - const Array1D<float>& shift) override; + const std::array<float, 2>& shift) override; std::shared_ptr<Grid> get_final_grid() override; diff --git a/idg-lib/src/CUDA/Generic/Generic.cpp b/idg-lib/src/CUDA/Generic/Generic.cpp index 21d292ad6d2bbb16368f18080789bb1630b16661..7bd45cd1e81c10b011ec629669dc4a39328695e9 100644 --- a/idg-lib/src/CUDA/Generic/Generic.cpp +++ b/idg-lib/src/CUDA/Generic/Generic.cpp @@ -123,10 +123,12 @@ std::shared_ptr<Grid> Generic::get_final_grid() { } std::unique_ptr<Plan> Generic::make_plan( - const int kernel_size, const Array1D<float>& frequencies, - const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, Plan::Options options) { + const int kernel_size, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, + Plan::Options options) { if (do_supports_wtiling() && !m_disable_wtiling) { options.w_step = m_cache_state.w_step; options.nr_w_layers = std::numeric_limits<int>::max(); @@ -141,7 +143,7 @@ std::unique_ptr<Plan> Generic::make_plan( } void Generic::init_cache(int subgrid_size, float cell_size, float w_step, - const Array1D<float>& shift) { + const std::array<float, 2>& shift) { // Initialize cache Proxy::init_cache(subgrid_size, cell_size, w_step, shift); diff --git a/idg-lib/src/CUDA/Generic/Generic.h b/idg-lib/src/CUDA/Generic/Generic.h index e1ece0bc5e62bb3237e80abf8662a3959aaed08d..13db417830537138d45cfd3acd3268090e1dd29d 100644 --- a/idg-lib/src/CUDA/Generic/Generic.h +++ b/idg-lib/src/CUDA/Generic/Generic.h @@ -64,14 +64,15 @@ class Generic : public CUDA { std::shared_ptr<Grid> get_final_grid() override; virtual std::unique_ptr<Plan> make_plan( - const int kernel_size, const Array1D<float>& frequencies, - const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, + const int kernel_size, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, Plan::Options options) override; void init_cache(int subgrid_size, float cell_size, float w_step, - const Array1D<float>& shift) override; + const std::array<float, 2>& shift) override; private: std::unique_ptr<cu::DeviceMemory> d_grid_; diff --git a/idg-lib/src/CUDA/Generic/routines/Imaging.cpp b/idg-lib/src/CUDA/Generic/routines/Imaging.cpp index 3490c43b4d4d82294f035f43258f0dc129b50ddb..d5d0ef55f28a6a50d86a2e1c610c7acca1574768 100644 --- a/idg-lib/src/CUDA/Generic/routines/Imaging.cpp +++ b/idg-lib/src/CUDA/Generic/routines/Imaging.cpp @@ -242,8 +242,8 @@ void Generic::run_imaging( // Launch gridder kernel device.launch_gridder( time_offset_current, nr_subgrids_current, nr_polarizations, grid_size, - subgrid_size, image_size, w_step, nr_channels, nr_stations, shift(0), - shift(1), d_uvw, d_wavenumbers, d_visibilities, d_spheroidal, + subgrid_size, image_size, w_step, nr_channels, nr_stations, shift[0], + shift[1], d_uvw, d_wavenumbers, d_visibilities, d_spheroidal, d_aterms, d_aterm_indices, d_metadata, *d_avg_aterm, d_subgrids); // Launch FFT @@ -294,8 +294,8 @@ void Generic::run_imaging( // Launch degridder kernel device.launch_degridder( time_offset_current, nr_subgrids_current, nr_polarizations, grid_size, - subgrid_size, image_size, w_step, nr_channels, nr_stations, shift(0), - shift(1), d_uvw, d_wavenumbers, d_visibilities, d_spheroidal, + subgrid_size, image_size, w_step, nr_channels, nr_stations, shift[0], + shift[1], d_uvw, d_wavenumbers, d_visibilities, d_spheroidal, d_aterms, d_aterm_indices, d_metadata, d_subgrids); executestream.record(gpuFinished[job_id]); diff --git a/idg-lib/src/CUDA/common/CUDA.cpp b/idg-lib/src/CUDA/common/CUDA.cpp index 0e15faee9af8223a2370388cd4d875f743736891..45cf269e7b249e38d8a0b38054b6ffd2ed823184 100644 --- a/idg-lib/src/CUDA/common/CUDA.cpp +++ b/idg-lib/src/CUDA/common/CUDA.cpp @@ -32,6 +32,7 @@ CUDA::~CUDA() { // contexts are free'ed, hence the explicit calls here. free_unified_grid(); free_buffers_wtiling(); + free_memory(); } void CUDA::init_devices() { diff --git a/idg-lib/src/CUDA/common/CUDA.h b/idg-lib/src/CUDA/common/CUDA.h index 8a4b9f467ea0e9f0ac7edc3a21db6d69a79bd03d..18d9761583e2e2e655bb05fd4afff2cd5748e1dd 100644 --- a/idg-lib/src/CUDA/common/CUDA.h +++ b/idg-lib/src/CUDA/common/CUDA.h @@ -119,31 +119,31 @@ class CUDA : public Proxy { const int nr_polarizations, const int subgrid_size, const float image_size, const float w_step, - const idg::Array1D<float>& shift, + const std::array<float, 2>& shift, const size_t bytes_free) const; void run_wtiles_to_grid(unsigned int subgrid_size, float image_size, - float w_step, const Array1D<float>& shift, + float w_step, const std::array<float, 2>& shift, WTileUpdateInfo& wtile_flush_info); void run_subgrids_to_wtiles(unsigned int nr_polarizations, unsigned int subgrid_offset, unsigned int nr_subgrids, unsigned int subgrid_size, float image_size, - float w_step, const Array1D<float>& shift, + float w_step, const std::array<float, 2>& shift, WTileUpdateSet& wtile_flush_set, cu::DeviceMemory& d_subgrids, cu::DeviceMemory& d_metadata); void run_wtiles_from_grid(unsigned int subgrid_size, float image_size, - float w_step, const Array1D<float>& shift, + float w_step, const std::array<float, 2>& shift, WTileUpdateInfo& wtile_initialize_info); void run_subgrids_from_wtiles(unsigned int nr_polarizations, unsigned int subgrid_offset, unsigned int nr_subgrids, unsigned int subgrid_size, float image_size, - float w_step, const Array1D<float>& shift, + float w_step, const std::array<float, 2>& shift, WTileUpdateSet& wtile_initialize_set, cu::DeviceMemory& d_subgrids, cu::DeviceMemory& d_metadata); diff --git a/idg-lib/src/CUDA/common/routines/WTiling.cpp b/idg-lib/src/CUDA/common/routines/WTiling.cpp index f5fd663352b7f1e20d0f543f5de4a0130cd30993..9454ecff2e8882f69ae1b35b60b89948a9bdbcb3 100644 --- a/idg-lib/src/CUDA/common/routines/WTiling.cpp +++ b/idg-lib/src/CUDA/common/routines/WTiling.cpp @@ -55,16 +55,15 @@ size_t CUDA::bytes_required_wtiling(const WTileUpdateSet& wtile_set, const int nr_polarizations, const int subgrid_size, const float image_size, const float w_step, - const idg::Array1D<float>& shift, + const std::array<float, 2>& shift, const size_t bytes_free) const { if (wtile_set.empty()) { return 0; } // Compute the maximum padded w-tile size for any w-tile in the set - int w_padded_tile_size = - compute_w_padded_tile_size_max(wtile_set, m_tile_size, subgrid_size, - image_size, w_step, shift(0), shift(1)); + int w_padded_tile_size = compute_w_padded_tile_size_max( + wtile_set, m_tile_size, subgrid_size, image_size, w_step, shift); // Compute the memory required for such a padded w-tile size_t sizeof_w_padded_tile = w_padded_tile_size * w_padded_tile_size * @@ -159,7 +158,7 @@ void CUDA::init_buffers_wtiling(unsigned int subgrid_size) { } void CUDA::run_wtiles_to_grid(unsigned int subgrid_size, float image_size, - float w_step, const Array1D<float>& shift, + float w_step, const std::array<float, 2>& shift, WTileUpdateInfo& wtile_flush_info) { // Load grid parameters unsigned int nr_polarizations = m_grid->get_z_dim(); @@ -192,7 +191,7 @@ void CUDA::run_wtiles_to_grid(unsigned int subgrid_size, float image_size, // Compute w_padded_tile_size for all tiles const float image_size_shift = - image_size + 2 * std::max(std::abs(shift(0)), std::abs(shift(1))); + image_size + 2 * std::max(std::abs(shift[0]), std::abs(shift[1])); std::vector<int> w_padded_tile_sizes = compute_w_padded_tile_sizes( tile_coordinates.data(), nr_tiles, w_step, image_size, image_size_shift, padded_tile_size); @@ -225,8 +224,9 @@ void CUDA::run_wtiles_to_grid(unsigned int subgrid_size, float image_size, } // Copy shift to device - cu::DeviceMemory d_shift(context, shift.bytes()); - executestream.memcpyHtoDAsync(d_shift, shift.data(), shift.bytes()); + const size_t sizeof_shift = shift.size() * sizeof(float); + cu::DeviceMemory d_shift(context, sizeof_shift); + executestream.memcpyHtoDAsync(d_shift, shift.data(), sizeof_shift); // FFT plan std::unique_ptr<cufft::C2C_2D> fft; @@ -386,7 +386,7 @@ void CUDA::run_wtiles_to_grid(unsigned int subgrid_size, float image_size, void CUDA::run_subgrids_to_wtiles( unsigned nr_polarizations, unsigned int subgrid_offset, unsigned int nr_subgrids, unsigned int subgrid_size, float image_size, - float w_step, const idg::Array1D<float>& shift, + float w_step, const std::array<float, 2>& shift, WTileUpdateSet& wtile_flush_set, cu::DeviceMemory& d_subgrids, cu::DeviceMemory& d_metadata) { // Load CUDA objects @@ -447,7 +447,7 @@ void CUDA::run_subgrids_to_wtiles( } void CUDA::run_wtiles_from_grid(unsigned int subgrid_size, float image_size, - float w_step, const Array1D<float>& shift, + float w_step, const std::array<float, 2>& shift, WTileUpdateInfo& wtile_initialize_info) { // Load grid parameters unsigned int nr_polarizations = m_grid->get_z_dim(); @@ -480,7 +480,7 @@ void CUDA::run_wtiles_from_grid(unsigned int subgrid_size, float image_size, // Compute w_padded_tile_size for all tiles const float image_size_shift = - image_size + 2 * std::max(std::abs(shift(0)), std::abs(shift(1))); + image_size + 2 * std::max(std::abs(shift[0]), std::abs(shift[1])); std::vector<int> w_padded_tile_sizes = compute_w_padded_tile_sizes( tile_coordinates.data(), nr_tiles, w_step, image_size, image_size_shift, padded_tile_size); @@ -517,8 +517,9 @@ void CUDA::run_wtiles_from_grid(unsigned int subgrid_size, float image_size, sizeof_tile_ids); // Copy shift to device - cu::DeviceMemory d_shift(context, shift.bytes()); - executestream.memcpyHtoDAsync(d_shift, shift.data(), shift.bytes()); + const size_t sizeof_shift = shift.size() * sizeof(float); + cu::DeviceMemory d_shift(context, sizeof_shift); + executestream.memcpyHtoDAsync(d_shift, shift.data(), sizeof_shift); // FFT plan std::unique_ptr<cufft::C2C_2D> fft; @@ -675,14 +676,12 @@ void CUDA::run_wtiles_from_grid(unsigned int subgrid_size, float image_size, } // end for tile_offset } -void CUDA::run_subgrids_from_wtiles(unsigned int nr_polarizations, - unsigned int subgrid_offset, - unsigned int nr_subgrids, - unsigned int subgrid_size, float image_size, - float w_step, const Array1D<float>& shift, - WTileUpdateSet& wtile_initialize_set, - cu::DeviceMemory& d_subgrids, - cu::DeviceMemory& d_metadata) { +void CUDA::run_subgrids_from_wtiles( + unsigned int nr_polarizations, unsigned int subgrid_offset, + unsigned int nr_subgrids, unsigned int subgrid_size, float image_size, + float w_step, const std::array<float, 2>& shift, + WTileUpdateSet& wtile_initialize_set, cu::DeviceMemory& d_subgrids, + cu::DeviceMemory& d_metadata) { // Load CUDA objects kernel::cuda::InstanceCUDA& device = get_device(0); cu::Stream& stream = device.get_execute_stream(); @@ -749,7 +748,7 @@ void CUDA::flush_wtiles() { float image_size = grid_size * cell_size; int subgrid_size = m_cache_state.subgrid_size; float w_step = m_cache_state.w_step; - const Array1D<float>& shift = m_cache_state.shift; + const std::array<float, 2>& shift = m_cache_state.shift; // Get all the remaining wtiles WTileUpdateInfo wtile_flush_info = m_wtiles.clear(); diff --git a/idg-lib/src/Hybrid/CUDA/GenericOptimized/GenericOptimized.cpp b/idg-lib/src/Hybrid/CUDA/GenericOptimized/GenericOptimized.cpp index cd236fbf2020a2c762c00561c2143e1d14462271..5f60767ab66a7a2275a795d03fbd843c35880203 100644 --- a/idg-lib/src/Hybrid/CUDA/GenericOptimized/GenericOptimized.cpp +++ b/idg-lib/src/Hybrid/CUDA/GenericOptimized/GenericOptimized.cpp @@ -63,10 +63,12 @@ GenericOptimized::~GenericOptimized() { * Plan */ std::unique_ptr<Plan> GenericOptimized::make_plan( - const int kernel_size, const Array1D<float>& frequencies, - const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, Plan::Options options) { + const int kernel_size, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, + Plan::Options options) { if (!m_disable_wtiling && !m_disable_wtiling_gpu) { options.w_step = m_cache_state.w_step; options.nr_w_layers = INT_MAX; @@ -165,7 +167,8 @@ std::shared_ptr<Grid> GenericOptimized::get_final_grid() { * Cache */ void GenericOptimized::init_cache(int subgrid_size, float cell_size, - float w_step, const Array1D<float>& shift) { + float w_step, + const std::array<float, 2>& shift) { // Initialize cache Proxy::init_cache(subgrid_size, cell_size, w_step, shift); diff --git a/idg-lib/src/Hybrid/CUDA/GenericOptimized/GenericOptimized.h b/idg-lib/src/Hybrid/CUDA/GenericOptimized/GenericOptimized.h index 404e57d932f6b3dcb2cb6284c9074ce02e0f78f8..0d4e9ac776a12037ec2bd13faa1884c598f228fe 100644 --- a/idg-lib/src/Hybrid/CUDA/GenericOptimized/GenericOptimized.h +++ b/idg-lib/src/Hybrid/CUDA/GenericOptimized/GenericOptimized.h @@ -44,13 +44,14 @@ class GenericOptimized : public cuda::CUDA { std::shared_ptr<Grid> get_final_grid() override; void init_cache(int subgrid_size, float cell_size, float w_step, - const Array1D<float>& shift) override; + const std::array<float, 2>& shift) override; std::unique_ptr<Plan> make_plan( - const int kernel_size, const Array1D<float>& frequencies, - const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, + const int kernel_size, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, Plan::Options options) override; private: diff --git a/idg-lib/src/Hybrid/CUDA/GenericOptimized/routines/Imaging.cpp b/idg-lib/src/Hybrid/CUDA/GenericOptimized/routines/Imaging.cpp index 219e6586eb6d74b72fdec54ce77369318f881f8f..63e43aec8cb3177727d66d8597e8a183b220907a 100644 --- a/idg-lib/src/Hybrid/CUDA/GenericOptimized/routines/Imaging.cpp +++ b/idg-lib/src/Hybrid/CUDA/GenericOptimized/routines/Imaging.cpp @@ -252,8 +252,8 @@ void GenericOptimized::run_imaging( // Launch gridder kernel device.launch_gridder( time_offset_current, nr_subgrids_current, nr_polarizations, grid_size, - subgrid_size, image_size, w_step, nr_channels, nr_stations, shift(0), - shift(1), d_uvw, d_wavenumbers, d_visibilities, d_spheroidal, + subgrid_size, image_size, w_step, nr_channels, nr_stations, shift[0], + shift[1], d_uvw, d_wavenumbers, d_visibilities, d_spheroidal, d_aterms, d_aterm_indices, d_metadata, *d_avg_aterm, d_subgrids); // Launch FFT @@ -352,8 +352,8 @@ void GenericOptimized::run_imaging( // Launch degridder kernel device.launch_degridder( time_offset_current, nr_subgrids_current, nr_polarizations, grid_size, - subgrid_size, image_size, w_step, nr_channels, nr_stations, shift(0), - shift(1), d_uvw, d_wavenumbers, d_visibilities, d_spheroidal, + subgrid_size, image_size, w_step, nr_channels, nr_stations, shift[0], + shift[1], d_uvw, d_wavenumbers, d_visibilities, d_spheroidal, d_aterms, d_aterm_indices, d_metadata, d_subgrids); executestream.record(gpuFinished[job_id]); diff --git a/idg-lib/src/common/ArrayTypes.h b/idg-lib/src/common/ArrayTypes.h index 283cb80bcbf579aad24f6cb3bc2432cd4c52afa2..de64005446ef28ba7c12932b138337a26e77ff59 100644 --- a/idg-lib/src/common/ArrayTypes.h +++ b/idg-lib/src/common/ArrayTypes.h @@ -8,6 +8,7 @@ #include <cassert> #include <omp.h> +#include <aocommon/xt/span.h> #include "auxiliary.h" #include "Types.h" @@ -47,6 +48,20 @@ class Array1D { Array1D(T* data, size_t size) : m_x_dim(size), m_memory(nullptr), m_buffer(data) {} + /** + * @brief Construct a new Array1D object from a Span + * + * @param data The Span that the Array will use. + * Must be avaible during the life time of the Array + * The user is responsible for allocation and deallocation. + */ + Array1D(const aocommon::xt::Span<T, 1>& data) + : m_x_dim(data.size()), + m_memory(nullptr), + // This const_cast simplifies the transition to XTensor. It will + // be removed at the end of the transition, together with Array1D. + m_buffer(const_cast<T*>(data.data())) {} + /** * @brief Construct a new Array 1 D object from a Memory object * @@ -263,6 +278,21 @@ class Array2D : public Array1D<T> { Array2D(T* data, size_t y_dim, size_t x_dim) : Array1D<T>(data, y_dim * x_dim), m_y_dim(y_dim), m_x_dim(x_dim) {} + /** + * @brief Construct a new Array2D object from a Span + * + * @param data The Span that the Array will use. + * Must be avaible during the life time of the Array + * The user is responsible for allocation and deallocation. + */ + Array2D(const aocommon::xt::Span<T, 2>& data) + : m_y_dim(data.shape(0)), m_x_dim(data.shape(1)) { + this->m_memory = nullptr; + // This const_cast simplifies the transition to XTensor. It will + // be removed at the end of the transition, together with Array2D. + this->m_buffer = const_cast<T*>(data.data()); + } + /** * @brief Construct a new Array2D object from a Memory object * @@ -413,6 +443,21 @@ class Array3D : public Array1D<T> { m_y_dim(y_dim), m_x_dim(x_dim) {} + /** + * @brief Construct a new Array3D object from a Span + * + * @param data The Span that the Array will use. + * Must be avaible during the life time of the Array + * The user is responsible for allocation and deallocation. + */ + Array3D(const aocommon::xt::Span<T, 3>& data) + : m_z_dim(data.shape(0)), m_y_dim(data.shape(1)), m_x_dim(data.shape(2)) { + this->m_memory = nullptr; + // This const_cast simplifies the transition to XTensor. It will + // be removed at the end of the transition, together with Array3D. + this->m_buffer = const_cast<T*>(data.data()); + } + /** * @brief Construct a new Array3D object from a Memory object * @@ -590,6 +635,24 @@ class Array4D : public Array1D<T> { m_y_dim(y_dim), m_x_dim(x_dim) {} + /** + * @brief Construct a new Array4D object from a Span + * + * @param data The Span that the Array will use. + * Must be avaible during the life time of the Array + * The user is responsible for allocation and deallocation. + */ + Array4D(const aocommon::xt::Span<T, 4>& data) + : m_w_dim(data.shape(0)), + m_z_dim(data.shape(1)), + m_y_dim(data.shape(2)), + m_x_dim(data.shape(3)) { + this->m_memory = nullptr; + // This const_cast simplifies the transition to XTensor. It will + // be removed at the end of the transition, together with Array4D. + this->m_buffer = const_cast<T*>(data.data()); + } + /** * @brief Construct a new Array4D object from a Memory object * diff --git a/idg-lib/src/common/Plan.cpp b/idg-lib/src/common/Plan.cpp index c7444876d2f41550cba53151b966b4d98c1aa6f1..171e9abdf6f4100354f6a0fcff24ed2bbef268a9 100644 --- a/idg-lib/src/common/Plan.cpp +++ b/idg-lib/src/common/Plan.cpp @@ -6,18 +6,26 @@ #include <algorithm> // max_element #include <memory.h> // memcpy +#include <xtensor/xview.hpp> +#include <xtensor/xsort.hpp> + #include "Plan.h" +#include "auxiliary.h" using namespace std; namespace idg { Plan::Plan(const int kernel_size, const int subgrid_size, const int grid_size, - const float cell_size, const Array1D<float>& shift, - const Array1D<float>& frequencies, const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, Options options) - : m_subgrid_size(subgrid_size), + const float cell_size, const std::array<float, 2>& shift, + const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, + Options options) + : m_shift(shift), + m_subgrid_size(subgrid_size), m_cell_size(cell_size), use_wtiles(false), m_options(options) { @@ -26,20 +34,21 @@ Plan::Plan(const int kernel_size, const int subgrid_size, const int grid_size, #endif WTiles dummy_wtiles; - m_shift(0) = shift(0); - m_shift(1) = shift(1); initialize(kernel_size, subgrid_size, grid_size, cell_size, frequencies, uvw, baselines, aterm_offsets, dummy_wtiles, options); } Plan::Plan(const int kernel_size, const int subgrid_size, const int grid_size, - const float cell_size, const Array1D<float>& shift, - const Array1D<float>& frequencies, const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, WTiles& wtiles, - Options options) - : m_subgrid_size(subgrid_size), + const float cell_size, const std::array<float, 2>& shift, + const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, + WTiles& wtiles, Options options) + : m_shift(shift), + m_subgrid_size(subgrid_size), m_cell_size(cell_size), use_wtiles(true), m_options(options) { @@ -47,8 +56,6 @@ Plan::Plan(const int kernel_size, const int subgrid_size, const int grid_size, cout << "Plan::" << __func__ << " (with WTiles)" << endl; #endif - m_shift(0) = shift(0); - m_shift(1) = shift(1); initialize(kernel_size, subgrid_size, grid_size, cell_size, frequencies, uvw, baselines, aterm_offsets, wtiles, options); } @@ -206,10 +213,11 @@ inline float meters_to_lambda(float meters, float frequency) { std::vector<std::pair<int, int>> make_channel_groups( float baseline_length, float uv_span_frequency, float image_size, - const Array1D<float>& frequencies, unsigned int max_nr_channels = 0) { + const aocommon::xt::Span<float, 1>& frequencies, + unsigned int max_nr_channels = 0) { std::vector<std::pair<int, int>> result; - unsigned int nr_channels = frequencies.get_x_dim(); + const size_t nr_channels = frequencies.size(); // There will be at most as many channel_groups as channels result.reserve(nr_channels); @@ -238,10 +246,11 @@ std::vector<std::pair<int, int>> make_channel_groups( void Plan::initialize( const int kernel_size, const int subgrid_size, const int grid_size, - const float cell_size, const Array1D<float>& frequencies, - const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, WTiles& wtiles, + const float cell_size, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, WTiles& wtiles, const Options& options) { #if defined(DEBUG) cout << "Plan::" << __func__ << endl; @@ -250,41 +259,33 @@ void Plan::initialize( std::clog << "grid_size : " << grid_size << std::endl; #endif - // Check arguments - assert(baselines.get_x_dim() == uvw.get_y_dim()); - // Initialize arguments - auto nr_baselines = uvw.get_y_dim(); - auto nr_timesteps = uvw.get_x_dim(); - auto nr_timeslots = aterm_offsets.get_x_dim() - 1; - auto nr_channels = frequencies.get_x_dim(); - auto image_size = cell_size * grid_size; // TODO: remove - auto wtile_size = wtiles.get_wtile_size(); + const size_t nr_baselines = uvw.shape(0); + assert(baselines.size() == nr_baselines); + const size_t nr_timesteps = uvw.shape(1); + const size_t nr_timeslots = aterm_offsets.size() - 1; + const size_t nr_channels = frequencies.size(); + const float image_size = cell_size * grid_size; // TODO: remove + const size_t wtile_size = wtiles.get_wtile_size(); // Get options m_w_step = options.w_step; - int nr_w_layers = options.nr_w_layers; - int max_nr_timesteps_per_subgrid = - min(options.max_nr_timesteps_per_subgrid, nr_timesteps); - int max_nr_channels_per_subgrid = options.max_nr_channels_per_subgrid; - bool plan_strict = options.plan_strict; - - // Spectral-line imaging - bool simulate_spectral_line = options.simulate_spectral_line; - auto nr_channels_ = nr_channels; - if (simulate_spectral_line) { - nr_channels = 1; - } + const size_t nr_w_layers = options.nr_w_layers; + const size_t max_nr_timesteps_per_subgrid = min( + static_cast<size_t>(options.max_nr_timesteps_per_subgrid), nr_timesteps); + const size_t max_nr_channels_per_subgrid = + options.max_nr_channels_per_subgrid; + const bool plan_strict = options.plan_strict; // Temporary metadata vector for individual baselines - int max_nr_subgrids_per_baseline = + const size_t max_nr_subgrids_per_baseline = max_nr_timesteps_per_subgrid > 0 ? ((nr_timesteps + max_nr_timesteps_per_subgrid) / max_nr_timesteps_per_subgrid) + 1 : nr_timesteps; - idg::Array2D<Metadata> metadata_(nr_baselines, - nr_channels * max_nr_subgrids_per_baseline); + xt::xtensor<Metadata, 2> metadata_( + {nr_baselines, nr_channels * max_nr_subgrids_per_baseline}); // Count the actual number of subgrids per baseline std::vector<unsigned int> nr_subgrids_per_baseline(nr_baselines); @@ -327,14 +328,14 @@ void Plan::initialize( // Compute uv coordinates in pixels struct DataPoint { - unsigned timestep; + unsigned int timestep; float u_pixels; float v_pixels; float w_lambda; }; // Allocate datapoints for first and last channel in a group - idg::Array2D<DataPoint> datapoints(nr_timesteps, 2); + xt::xtensor<DataPoint, 2> datapoints({nr_timesteps, 2}); for (auto channel_group : channel_groups) { auto channel_begin = channel_group.first; @@ -376,22 +377,22 @@ void Plan::initialize( while (time_offset < nr_timesteps) { // Create subgrid subgrid.reset(); - int nr_timesteps_subgrid = 0; + size_t nr_timesteps_subgrid = 0; // Load first visibility - DataPoint first_datapoint = datapoints(time_offset, 0); - const int first_timestep = first_datapoint.timestep; + const DataPoint first_datapoint = datapoints(time_offset, 0); + const size_t first_timestep = first_datapoint.timestep; // Iterate all datapoints for (; time_offset < nr_timesteps; time_offset++) { // Visibility for first channel - DataPoint visibility0 = datapoints(time_offset, 0); + const DataPoint visibility0 = datapoints(time_offset, 0); const float u_pixels0 = visibility0.u_pixels; const float v_pixels0 = visibility0.v_pixels; const float w_lambda0 = visibility0.w_lambda; // Visibility for last channel - DataPoint visibility1 = datapoints(time_offset, 1); + const DataPoint visibility1 = datapoints(time_offset, 1); const float u_pixels1 = visibility1.u_pixels; const float v_pixels1 = visibility1.v_pixels; @@ -431,7 +432,7 @@ void Plan::initialize( } // Compute time index for first visibility on subgrid - auto time_index = bl * nr_timesteps + first_timestep; + const size_t time_index = bl * nr_timesteps + first_timestep; // Finish subgrid subgrid.finish(); @@ -439,8 +440,8 @@ void Plan::initialize( // Add subgrid to metadata if (subgrid.in_range()) { Metadata m = { - .time_index = (int)time_index, // time index - .nr_timesteps = nr_timesteps_subgrid, // nr of timesteps + .time_index = static_cast<int>(time_index), + .nr_timesteps = static_cast<int>(nr_timesteps_subgrid), .channel_begin = channel_begin, .channel_end = channel_end, .baseline = baseline, // baselines @@ -454,18 +455,6 @@ void Plan::initialize( unsigned subgrid_idx = nr_subgrids_per_baseline[bl]; metadata_(bl, subgrid_idx++) = m; - // Add additional subgrids for subsequent frequencies - if (simulate_spectral_line) { - for (unsigned c = 1; c < nr_channels_; c++) { - // Compute shifted subgrid for current frequency - float shift = frequencies(c) / frequencies(0); - Metadata m = metadata_(bl, subgrid_idx); - m.coordinate.x *= shift; - m.coordinate.y *= shift; - metadata_(bl, subgrid_idx++) = m; - } - } - // Update number of subgrids nr_subgrids_per_baseline[bl] = subgrid_idx; } else if (plan_strict) { @@ -530,7 +519,7 @@ void Plan::initialize( } // end for bl // Reserve aterm indices - aterm_indices.resize(nr_baselines * nr_timesteps); + aterm_indices.resize({nr_baselines, nr_timesteps}); // Set aterm index for every timestep #pragma omp parallel for @@ -545,31 +534,31 @@ void Plan::initialize( // The aterm index is equal to the timeslot const unsigned int aterm_index = timeslot; - // Determine number of timesteps in current aterm - const unsigned nr_timesteps_per_aterm = + // Determine timesteps in current aterm + const unsigned int nr_timesteps_per_aterm = next_aterm_offset - current_aterm_offset; + const unsigned int first_aterm = time_idx; + const unsigned int last_aterm = time_idx + nr_timesteps_per_aterm; - for (unsigned timestep = 0; timestep < nr_timesteps_per_aterm; - timestep++) { - aterm_indices[bl * nr_timesteps + time_idx++] = aterm_index; - } + xt::view(aterm_indices, bl, xt::range(first_aterm, last_aterm)) = + aterm_index; + + time_idx += nr_timesteps_per_aterm; } } - // Set nr_aterms #pragma omp parallel for - for (unsigned i = 0; i < metadata.size(); i++) { - auto& m = metadata[i]; - auto aterm_index = aterm_indices[m.time_index]; - auto nr_aterms = 1; - for (auto time = 0; time < m.nr_timesteps; time++) { - auto aterm_index_current = aterm_indices[m.time_index + time]; + for (size_t i = 0; i < metadata.size(); ++i) { + Metadata& m = metadata[i]; + size_t aterm_index = aterm_indices[m.time_index]; + size_t nr_aterms = 1; + for (size_t time = 0; time < static_cast<size_t>(m.nr_timesteps); ++time) { + const size_t aterm_index_current = aterm_indices[m.time_index + time]; if (aterm_index != aterm_index_current) { - nr_aterms++; + ++nr_aterms; aterm_index = aterm_index_current; } } - m.nr_aterms = nr_aterms; } @@ -678,8 +667,11 @@ void Plan::copy_metadata(void* ptr) const { } void Plan::copy_aterm_indices(void* ptr) const { - memcpy(ptr, get_aterm_indices_ptr(), - aterm_indices.size() * sizeof(unsigned int)); + const size_t nr_baselines = aterm_indices.shape(0); + const size_t nr_timesteps = aterm_indices.shape(1); + const size_t sizeof_aterm_indices = + auxiliary::sizeof_aterm_indices(nr_baselines, nr_timesteps); + memcpy(ptr, aterm_indices.data(), sizeof_aterm_indices); } const unsigned int* Plan::get_aterm_indices_ptr(int bl) const { diff --git a/idg-lib/src/common/Plan.h b/idg-lib/src/common/Plan.h index 4846b5b97af21f128fc8f17b116a6f2a24362b93..3875b3950b54d4e8e3de3f3c8865f253e75f5942 100644 --- a/idg-lib/src/common/Plan.h +++ b/idg-lib/src/common/Plan.h @@ -10,10 +10,11 @@ #include <cmath> #include <numeric> #include <iterator> + +#include <aocommon/xt/span.h> #include <omp.h> #include "Types.h" -#include "ArrayTypes.h" #include "WTiles.h" namespace idg { @@ -53,10 +54,6 @@ class Plan { // zero means no limit unsigned max_nr_channels_per_subgrid = 0; - // consider only first channel when creating subgrids, - // add additional subgrids for every subsequent frequencies - bool simulate_spectral_line = false; - // Imaging mode Mode mode = Mode::FULL_POLARIZATION; }; @@ -67,16 +64,21 @@ class Plan { Plan(Plan&&) = default; Plan(const int kernel_size, const int subgrid_size, const int grid_size, - const float cell_size, const Array1D<float>& shift, - const Array1D<float>& frequencies, const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, Options options = Options()); + const float cell_size, const std::array<float, 2>& shift, + const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, + Options options = Options()); Plan(const int kernel_size, const int subgrid_size, const int grid_size, - const float cell_size, const Array1D<float>& shift, - const Array1D<float>& frequencies, const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, WTiles& wtiles, + const float cell_size, const std::array<float, 2>& shift, + const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, WTiles& wtiles, Options options = Options()); // Destructor @@ -84,10 +86,11 @@ class Plan { void initialize( const int kernel_size, const int subgrid_size, const int grid_size, - const float cell_size, const Array1D<float>& frequencies, - const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, WTiles& wtiles, + const float cell_size, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, WTiles& wtiles, const Options& options); // options @@ -171,11 +174,11 @@ class Plan { int get_subgrid_size() const { return m_subgrid_size; } float get_w_step() const { return m_w_step; } - const Array1D<float>& get_shift() const { return m_shift; } + const std::array<float, 2>& get_shift() const { return m_shift; } float get_cell_size() const { return m_cell_size; } private: - Array1D<float> m_shift{2}; + std::array<float, 2> m_shift; int m_subgrid_size; float m_w_step; float m_cell_size; @@ -185,7 +188,7 @@ class Plan { std::vector<int> total_nr_visibilities_per_baseline; WTileUpdateSet m_wtile_initialize_set; WTileUpdateSet m_wtile_flush_set; - std::vector<unsigned int> aterm_indices; + xt::xtensor<unsigned int, 2> aterm_indices; bool use_wtiles; Options m_options; }; // class Plan diff --git a/idg-lib/src/common/PlanC.cpp b/idg-lib/src/common/PlanC.cpp index e56ad85fd3997ef98b4756df3540e23a51350aa2..e2b3a62e8f6c0deb7558a7128a60107bcd4be735 100644 --- a/idg-lib/src/common/PlanC.cpp +++ b/idg-lib/src/common/PlanC.cpp @@ -28,22 +28,28 @@ struct idg::Plan* Plan_init(int kernel_size, int subgrid_size, int grid_size, int baselines_nr_baselines, int baselines_two, unsigned int* aterm_offsets, int aterm_offsets_nr_timeslots) { - idg::Array1D<float> shift_array(3); - shift_array(0) = 0; - shift_array(1) = 0; - shift_array(2) = 0; - idg::Array1D<float> frequencies_array(frequencies, frequencies_nr_channels); + std::array<float, 2> shift{0.0f, 0.0f}; + const std::array<size_t, 1> frequencies_shape{ + static_cast<size_t>(frequencies_nr_channels)}; + aocommon::xt::Span<float, 1> frequencies_span = + aocommon::xt::CreateSpan(frequencies, frequencies_shape); assert(uvw_nr_coordinates == 3); - idg::Array2D<idg::UVW<float>> uvw_array(uvw, uvw_nr_baselines, - uvw_nr_timesteps); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines_array( - baselines, baselines_nr_baselines); - idg::Array1D<unsigned int> aterm_offsets_array(aterm_offsets, - aterm_offsets_nr_timeslots); - - return new idg::Plan(kernel_size, subgrid_size, grid_size, cell_size, - shift_array, frequencies_array, uvw_array, - baselines_array, aterm_offsets_array); + const std::array<size_t, 2> uvw_shape{static_cast<size_t>(uvw_nr_baselines), + static_cast<size_t>(uvw_nr_timesteps)}; + aocommon::xt::Span<idg::UVW<float>, 2> uvw_span = + aocommon::xt::CreateSpan(uvw, uvw_shape); + const std::array<size_t, 1> baselines_shape{ + static_cast<size_t>(baselines_nr_baselines)}; + aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1> baselines_span = + aocommon::xt::CreateSpan(baselines, baselines_shape); + const std::array<size_t, 1> aterm_offsets_shape{ + static_cast<size_t>(aterm_offsets_nr_timeslots)}; + aocommon::xt::Span<unsigned int, 1> aterm_offsets_span = + aocommon::xt::CreateSpan(aterm_offsets, aterm_offsets_shape); + + return new idg::Plan(kernel_size, subgrid_size, grid_size, cell_size, shift, + frequencies_span, uvw_span, baselines_span, + aterm_offsets_span); } } // extern "C" diff --git a/idg-lib/src/common/Proxy.cpp b/idg-lib/src/common/Proxy.cpp index 2be127b1f4ce2a573e88685aa11512be2fee68b8..8b0306f40eb3abc6018992747bbbb9fe66e36b4a 100644 --- a/idg-lib/src/common/Proxy.cpp +++ b/idg-lib/src/common/Proxy.cpp @@ -38,6 +38,27 @@ void Proxy::gridding( aterm_offsets, spheroidal); } +void Proxy::gridding( + const Plan& plan, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<std::complex<float>, 4>& visibilities, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4>& aterms, + const aocommon::xt::Span<unsigned int, 1>& aterms_offsets, + const aocommon::xt::Span<float, 2>& taper) { + const Array1D<float> frequencies_array(frequencies); + const Array4D<std::complex<float>> visibilities_array(visibilities); + const Array2D<UVW<float>> uvw_array(uvw); + const Array1D<std::pair<unsigned int, unsigned int>> baselines_array( + baselines); + const Array4D<Matrix2x2<std::complex<float>>> aterms_array(aterms); + const Array1D<unsigned int> aterms_offsets_array(aterms_offsets); + const Array2D<float> taper_array(taper); + gridding(plan, frequencies_array, visibilities_array, uvw_array, + baselines_array, aterms_array, aterms_offsets_array, taper_array); +} + void Proxy::degridding( const Plan& plan, const Array1D<float>& frequencies, Array4D<std::complex<float>>& visibilities, const Array2D<UVW<float>>& uvw, @@ -60,6 +81,27 @@ void Proxy::degridding( aterm_offsets, spheroidal); } +void Proxy::degridding( + const Plan& plan, const aocommon::xt::Span<float, 1>& frequencies, + aocommon::xt::Span<std::complex<float>, 4>& visibilities, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4>& aterms, + const aocommon::xt::Span<unsigned int, 1>& aterms_offsets, + const aocommon::xt::Span<float, 2>& taper) { + const Array1D<float> frequencies_array(frequencies); + Array4D<std::complex<float>> visibilities_array(visibilities); + const Array2D<UVW<float>> uvw_array(uvw); + const Array1D<std::pair<unsigned int, unsigned int>> baselines_array( + baselines); + const Array4D<Matrix2x2<std::complex<float>>> aterms_array(aterms); + const Array1D<unsigned int> aterms_offsets_array(aterms_offsets); + const Array2D<float> taper_array(taper); + degridding(plan, frequencies_array, visibilities_array, uvw_array, + baselines_array, aterms_array, aterms_offsets_array, taper_array); +} + void Proxy::calibrate_init( const unsigned int kernel_size, const Array2D<float>& frequencies, Array4D<std::complex<float>>& visibilities, Array4D<float>& weights, @@ -96,7 +138,7 @@ void Proxy::calibrate_init( auto nr_timesteps = visibilities.get_z_dim(); auto nr_correlations = visibilities.get_x_dim(); assert(nr_correlations == 4); - auto nr_baselines = baselines.get_x_dim(); + const size_t nr_baselines = baselines.size(); auto nr_channel_blocks = frequencies.get_y_dim(); auto nr_channels_per_block = frequencies.get_x_dim(); @@ -188,14 +230,20 @@ void Proxy::calibrate_init( plans[i].reserve(nr_channel_blocks); for (unsigned int channel_block = 0; channel_block < nr_channel_blocks; channel_block++) { - Array1D<float> frequencies_channel_block(frequencies.data(channel_block), - nr_channels_per_block); + const std::array<size_t, 1> frequencies_channel_block_shape{ + nr_channels_per_block}; + auto frequencies_channel_block = aocommon::xt::CreateSpan( + frequencies.data(channel_block), frequencies_channel_block_shape); + const std::array<size_t, 1> aterm_offsets_shape{aterm_offsets.size()}; + auto aterm_offsets_span = + aocommon::xt::CreateSpan(aterm_offsets.data(), aterm_offsets_shape); + const std::array<size_t, 2> uvw_shape{nr_antennas - 1, nr_timesteps}; + const std::array<size_t, 1> baselines_shape{nr_antennas - 1}; plans[i].push_back(make_plan( kernel_size, frequencies_channel_block, - Array2D<UVW<float>>(uvw1.data(i), nr_antennas - 1, nr_timesteps), - Array1D<std::pair<unsigned int, unsigned int>>(baselines1.data(i), - nr_antennas - 1), - aterm_offsets, options)); + aocommon::xt::CreateSpan(uvw1.data(i), uvw_shape), + aocommon::xt::CreateSpan(baselines1.data(i), baselines_shape), + aterm_offsets_span, options)); } } diff --git a/idg-lib/src/common/Proxy.h b/idg-lib/src/common/Proxy.h index d07c088932bcbe5975b778380c616ac52352543c..48ae4779d522fb08a3c5e1ce45fe76872e83bb08 100644 --- a/idg-lib/src/common/Proxy.h +++ b/idg-lib/src/common/Proxy.h @@ -10,12 +10,16 @@ #include <cstring> #include <utility> // pair +#include <aocommon/xt/span.h> + +#include "ArrayTypes.h" #include "RuntimeWrapper.h" #include "ProxyInfo.h" #include "Types.h" #include "Plan.h" #include "Report.h" #include "Exception.h" +#include "Tensor.h" namespace idg { enum DomainAtoDomainB { @@ -81,6 +85,16 @@ class Proxy { const Array1D<unsigned int>& aterm_offsets, const Array2D<float>& taper); + void gridding( + const Plan& plan, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<std::complex<float>, 4>& visibilities, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4>& aterms, + const aocommon::xt::Span<unsigned int, 1>& aterms_offsets, + const aocommon::xt::Span<float, 2>& taper); + /** * @brief Degrid (predict) visibilities, applying A-terms. * @@ -120,6 +134,16 @@ class Proxy { const Array4D<Matrix2x2<std::complex<float>>>& aterms, const Array1D<unsigned int>& aterm_offsets, const Array2D<float>& taper); + void degridding( + const Plan& plan, const aocommon::xt::Span<float, 1>& frequencies, + aocommon::xt::Span<std::complex<float>, 4>& visibilities, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4>& aterms, + const aocommon::xt::Span<unsigned int, 1>& aterms_offsets, + const aocommon::xt::Span<float, 2>& taper); + /** * @brief Prepare a calibration cycle * @@ -276,6 +300,37 @@ class Proxy { return Array4D<T>(allocate_memory(bytes), d_dim, c_dim, b_dim, a_dim); }; + template <typename T, size_t Dimensions> + Tensor<T, Dimensions> allocate_tensor( + const std::initializer_list<size_t> shape) { + assert(shape.size() == Dimensions); + std::array<size_t, Dimensions> shape_array; + size_t bytes = sizeof(T); + for (size_t i = 0; i < shape.size(); i++) { + const size_t dimension = *(shape.begin() + i); + shape_array[i] = dimension; + bytes *= dimension; + } + return Tensor<T, Dimensions>(allocate_memory(bytes), shape_array); + } + + template <typename T, size_t Dimensions> + aocommon::xt::Span<T, Dimensions> allocate_span( + const std::initializer_list<size_t> shape) { + assert(shape.size() == Dimensions); + std::array<size_t, Dimensions> shape_array; + size_t bytes = sizeof(T); + for (size_t i = 0; i < shape.size(); i++) { + const size_t dimension = *(shape.begin() + i); + shape_array[i] = dimension; + bytes *= dimension; + } + std::unique_ptr<auxiliary::Memory> memory = allocate_memory(bytes); + T* ptr = reinterpret_cast<T*>(memory->data()); + memory_.push_back(std::move(memory)); + return aocommon::xt::CreateSpan(ptr, shape_array); + } + //! Methods for grid management virtual std::shared_ptr<Grid> allocate_grid(size_t nr_w_layers, size_t nr_correlations, @@ -320,12 +375,11 @@ class Proxy { * @param shift */ virtual void init_cache(int subgrid_size, float cell_size, float w_step, - const Array1D<float>& shift) { + const std::array<float, 2>& shift) { m_cache_state.subgrid_size = subgrid_size; m_cache_state.cell_size = cell_size; m_cache_state.w_step = w_step; - m_cache_state.shift(0) = shift(0); - m_cache_state.shift(1) = shift(1); + m_cache_state.shift = shift; }; // The cache needs to have been initialized by call to init_cache first @@ -351,10 +405,11 @@ class Proxy { * @return std::unique_ptr<Plan> */ virtual std::unique_ptr<Plan> make_plan( - const int kernel_size, const Array1D<float>& frequencies, - const Array2D<UVW<float>>& uvw, - const Array1D<std::pair<unsigned int, unsigned int>>& baselines, - const Array1D<unsigned int>& aterm_offsets, + const int kernel_size, const aocommon::xt::Span<float, 1>& frequencies, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& + baselines, + const aocommon::xt::Span<unsigned int, 1>& aterm_offsets, Plan::Options options = Plan::Options()) { options.w_step = m_cache_state.w_step; return std::unique_ptr<Plan>( @@ -467,9 +522,14 @@ class Proxy { int subgrid_size; float cell_size; float w_step; - Array1D<float> shift{2}; + std::array<float, 2> shift; } m_cache_state; + void free_memory() { memory_.clear(); }; + + private: + std::vector<std::unique_ptr<auxiliary::Memory>> memory_; + }; // end class Proxy } // namespace proxy diff --git a/idg-lib/src/common/ProxyC.cpp b/idg-lib/src/common/ProxyC.cpp index 7d632db7330b711643060b3fcfa64484b9066a55..fb6010dd7e876e78f71208d85a29a2a834d6e63b 100644 --- a/idg-lib/src/common/ProxyC.cpp +++ b/idg-lib/src/common/ProxyC.cpp @@ -44,17 +44,35 @@ void Proxy_gridding(struct Proxy* p, int kernel_size, int subgrid_size, std::pair<unsigned int, unsigned int>* baselines, std::complex<float>* aterms, unsigned int* aterm_offsets, float* taper) { - idg::Array1D<float> frequencies_(frequencies, nr_channels); - idg::Array4D<std::complex<float>> visibilities_( - visibilities, nr_baselines, nr_timesteps, nr_channels, nr_correlations); - idg::Array2D<idg::UVW<float>> uvw_(uvw, nr_baselines, nr_timesteps); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines_(baselines, - nr_baselines); - idg::Array4D<idg::Matrix2x2<std::complex<float>>> aterms_( - (idg::Matrix2x2<std::complex<float>>*)aterms, nr_timeslots, nr_stations, - subgrid_size, subgrid_size); - idg::Array1D<unsigned int> aterm_offsets_(aterm_offsets, nr_timeslots + 1); - idg::Array2D<float> taper_(taper, subgrid_size, subgrid_size); + const std::array<size_t, 1> frequencies_shape{ + static_cast<size_t>(nr_channels)}; + const std::array<size_t, 2> uvw_shape{static_cast<size_t>(nr_baselines), + static_cast<size_t>(nr_timesteps)}; + const std::array<size_t, 4> visibilities_shape{ + static_cast<size_t>(nr_baselines), static_cast<size_t>(nr_timesteps), + static_cast<size_t>(nr_channels), static_cast<size_t>(nr_correlations)}; + const std::array<size_t, 1> baselines_shape{ + static_cast<size_t>(nr_baselines)}; + const std::array<size_t, 4> aterms_shape{ + static_cast<size_t>(nr_timeslots), static_cast<size_t>(nr_stations), + static_cast<size_t>(subgrid_size), static_cast<size_t>(subgrid_size)}; + const std::array<size_t, 1> aterm_offsets_shape{ + static_cast<size_t>(nr_timeslots + 1)}; + const std::array<size_t, 2> taper_shape{static_cast<size_t>(subgrid_size), + static_cast<size_t>(subgrid_size)}; + + auto frequencies_span = + aocommon::xt::CreateSpan(frequencies, frequencies_shape); + auto uvw_span = aocommon::xt::CreateSpan(uvw, uvw_shape); + auto visibilities_span = + aocommon::xt::CreateSpan(visibilities, visibilities_shape); + auto baselines_span = aocommon::xt::CreateSpan(baselines, baselines_shape); + auto aterms_span = aocommon::xt::CreateSpan( + reinterpret_cast<idg::Matrix2x2<std::complex<float>>*>(aterms), + aterms_shape); + auto aterm_offsets_span = + aocommon::xt::CreateSpan(aterm_offsets, aterm_offsets_shape); + auto taper_span = aocommon::xt::CreateSpan(taper, taper_shape); idg::Plan::Options options; options.mode = nr_correlations == 4 ? idg::Plan::Mode::FULL_POLARIZATION @@ -62,12 +80,12 @@ void Proxy_gridding(struct Proxy* p, int kernel_size, int subgrid_size, std::unique_ptr<idg::Plan> plan = ExitOnException( &idg::proxy::Proxy::make_plan, reinterpret_cast<idg::proxy::Proxy*>(p), - kernel_size, frequencies_, uvw_, baselines_, aterm_offsets_, options); + kernel_size, frequencies_span, uvw_span, baselines_span, + aterm_offsets_span, options); - ExitOnException(&idg::proxy::Proxy::gridding, - reinterpret_cast<idg::proxy::Proxy*>(p), *plan, frequencies_, - visibilities_, uvw_, baselines_, aterms_, aterm_offsets_, - taper_); + reinterpret_cast<idg::proxy::Proxy*>(p)->gridding( + *plan, frequencies_span, visibilities_span, uvw_span, baselines_span, + aterms_span, aterm_offsets_span, taper_span); } void Proxy_degridding(struct Proxy* p, int kernel_size, int subgrid_size, @@ -78,17 +96,35 @@ void Proxy_degridding(struct Proxy* p, int kernel_size, int subgrid_size, std::pair<unsigned int, unsigned int>* baselines, std::complex<float>* aterms, unsigned int* aterm_offsets, float* taper) { - idg::Array1D<float> frequencies_(frequencies, nr_channels); - idg::Array4D<std::complex<float>> visibilities_( - visibilities, nr_baselines, nr_timesteps, nr_channels, nr_correlations); - idg::Array2D<idg::UVW<float>> uvw_(uvw, nr_baselines, nr_timesteps); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines_(baselines, - nr_baselines); - idg::Array4D<idg::Matrix2x2<std::complex<float>>> aterms_( - (idg::Matrix2x2<std::complex<float>>*)aterms, nr_timeslots, nr_stations, - subgrid_size, subgrid_size); - idg::Array1D<unsigned int> aterm_offsets_(aterm_offsets, nr_timeslots + 1); - idg::Array2D<float> taper_(taper, subgrid_size, subgrid_size); + const std::array<size_t, 1> frequencies_shape{ + static_cast<size_t>(nr_channels)}; + const std::array<size_t, 2> uvw_shape{static_cast<size_t>(nr_baselines), + static_cast<size_t>(nr_timesteps)}; + const std::array<size_t, 4> visibilities_shape{ + static_cast<size_t>(nr_baselines), static_cast<size_t>(nr_timesteps), + static_cast<size_t>(nr_channels), static_cast<size_t>(nr_correlations)}; + const std::array<size_t, 1> baselines_shape{ + static_cast<size_t>(nr_baselines)}; + const std::array<size_t, 4> aterms_shape{ + static_cast<size_t>(nr_timeslots), static_cast<size_t>(nr_stations), + static_cast<size_t>(subgrid_size), static_cast<size_t>(subgrid_size)}; + const std::array<size_t, 1> aterm_offsets_shape{ + static_cast<size_t>(nr_timeslots + 1)}; + const std::array<size_t, 2> taper_shape{static_cast<size_t>(subgrid_size), + static_cast<size_t>(subgrid_size)}; + + auto frequencies_span = + aocommon::xt::CreateSpan(frequencies, frequencies_shape); + auto uvw_span = aocommon::xt::CreateSpan(uvw, uvw_shape); + auto visibilities_span = + aocommon::xt::CreateSpan(visibilities, visibilities_shape); + auto baselines_span = aocommon::xt::CreateSpan(baselines, baselines_shape); + auto aterms_span = aocommon::xt::CreateSpan( + reinterpret_cast<idg::Matrix2x2<std::complex<float>>*>(aterms), + aterms_shape); + auto aterm_offsets_span = + aocommon::xt::CreateSpan(aterm_offsets, aterm_offsets_shape); + auto taper_span = aocommon::xt::CreateSpan(taper, taper_shape); idg::Plan::Options options; options.mode = nr_correlations == 4 ? idg::Plan::Mode::FULL_POLARIZATION @@ -96,20 +132,20 @@ void Proxy_degridding(struct Proxy* p, int kernel_size, int subgrid_size, std::unique_ptr<idg::Plan> plan = ExitOnException( &idg::proxy::Proxy::make_plan, reinterpret_cast<idg::proxy::Proxy*>(p), - kernel_size, frequencies_, uvw_, baselines_, aterm_offsets_, options); + kernel_size, frequencies_span, uvw_span, baselines_span, + aterm_offsets_span, options); - ExitOnException(&idg::proxy::Proxy::degridding, - reinterpret_cast<idg::proxy::Proxy*>(p), *plan, frequencies_, - visibilities_, uvw_, baselines_, aterms_, aterm_offsets_, - taper_); + reinterpret_cast<idg::proxy::Proxy*>(p)->degridding( + *plan, frequencies_span, visibilities_span, uvw_span, baselines_span, + aterms_span, aterm_offsets_span, taper_span); } void Proxy_init_cache(struct Proxy* p, unsigned int subgrid_size, const float cell_size, float w_step, float* shift) { - idg::Array1D<float> shift_(shift, 2); + const std::array<float, 2> shift_array{shift[0], shift[1]}; ExitOnException(&idg::proxy::Proxy::init_cache, reinterpret_cast<idg::proxy::Proxy*>(p), subgrid_size, - cell_size, w_step, shift_); + cell_size, w_step, shift_array); } void Proxy_calibrate_init(struct Proxy* p, unsigned int kernel_size, @@ -131,8 +167,11 @@ void Proxy_calibrate_init(struct Proxy* p, unsigned int kernel_size, nr_timesteps, nr_channels, nr_correlations); idg::Array2D<idg::UVW<float>> uvw_((idg::UVW<float>*)uvw, nr_baselines, nr_timesteps); - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines_( - (std::pair<unsigned int, unsigned int>*)baselines, nr_baselines); + const std::array<size_t, 1> baselines_shape{ + static_cast<size_t>(nr_baselines)}; + auto baselines_ = aocommon::xt::CreateSpan( + reinterpret_cast<std::pair<unsigned int, unsigned int>*>(baselines), + baselines_shape); idg::Array1D<unsigned int> aterm_offsets_(aterm_offsets, nr_timeslots + 1); idg::Array2D<float> spheroidal_(spheroidal, subgrid_size, subgrid_size); diff --git a/idg-lib/src/common/Tensor.h b/idg-lib/src/common/Tensor.h new file mode 100644 index 0000000000000000000000000000000000000000..bcf6c5d8f0068b6388c178b8f7cbb477a7d79be3 --- /dev/null +++ b/idg-lib/src/common/Tensor.h @@ -0,0 +1,27 @@ +// Copyright (C) 2023 ASTRON (Netherlands Institute for Radio Astronomy) +// SPDX-License-Identifier: GPL-3.0-or-later + +#include <aocommon/xt/span.h> + +#include "auxiliary.h" + +namespace idg { + +/// Structure that holds a span and the memory allocated for that span. +template <typename T, size_t Dimensions> +class Tensor { + public: + Tensor(std::unique_ptr<auxiliary::Memory> memory, + const std::array<size_t, Dimensions>& shape) + : memory_(std::move(memory)), + span_(aocommon::xt::CreateSpan<T, Dimensions>( + reinterpret_cast<T*>(memory_->data()), shape)){}; + + aocommon::xt::Span<T, Dimensions>& Span() { return span_; } + + private: + std::unique_ptr<auxiliary::Memory> memory_; + aocommon::xt::Span<T, Dimensions> span_; +}; + +} // namespace idg \ No newline at end of file diff --git a/idg-lib/src/common/WTiles.cpp b/idg-lib/src/common/WTiles.cpp index fd5a20b995b9ed74d9c1d3354218f91aa2b799ff..287c2422b0adaa7f4b9c0d91048a4f55eef24dc4 100644 --- a/idg-lib/src/common/WTiles.cpp +++ b/idg-lib/src/common/WTiles.cpp @@ -116,7 +116,7 @@ std::vector<int> compute_w_padded_tile_sizes(const idg::Coordinate* coordinates, int compute_w_padded_tile_size_max(const WTileUpdateSet& wtile_set, const int tile_size, const int subgrid_size, const float image_size, const float w_step, - const float shift_l, const float shift_m) { + const std::array<float, 2>& shift) { int w_padded_tile_size_max = 0; for (unsigned int i = 0; i < wtile_set.size(); i++) { @@ -126,7 +126,7 @@ int compute_w_padded_tile_size_max(const WTileUpdateSet& wtile_set, wtile_info.wtile_coordinates; const int padded_tile_size = tile_size + subgrid_size; const float image_size_shift = - image_size + 2 * std::max(std::abs(shift_l), std::abs(shift_m)); + image_size + 2 * std::max(std::abs(shift[0]), std::abs(shift[1])); const std::vector<int> w_padded_tile_sizes = compute_w_padded_tile_sizes( tile_coordinates.data(), nr_tiles, w_step, image_size, image_size_shift, padded_tile_size); diff --git a/idg-lib/src/common/WTiles.h b/idg-lib/src/common/WTiles.h index c9df5c11e73073cc047907db551e8f84bcb369b1..ab921977cad002edcce8ede6e3a8eea495e834dd 100644 --- a/idg-lib/src/common/WTiles.h +++ b/idg-lib/src/common/WTiles.h @@ -191,7 +191,7 @@ std::vector<int> compute_w_padded_tile_sizes(const idg::Coordinate* coordinates, int compute_w_padded_tile_size_max(const WTileUpdateSet& wtile_set, const int tile_size, const int subgrid_size, const float image_size, const float w_step, - const float shift_l, const float shift_m); + const std::array<float, 2>& shift); } // namespace idg #endif diff --git a/idg-util/src/initialize/Data.cpp b/idg-util/src/initialize/Data.cpp index 0c96fadf37d20e880e0030b8b5a6d46f01373cd0..ca6688d4d0fed1ca62984418396604404d25efc8 100644 --- a/idg-util/src/initialize/Data.cpp +++ b/idg-util/src/initialize/Data.cpp @@ -215,40 +215,33 @@ void Data::limit_nr_baselines(unsigned int n) { std::swap(m_baselines, baselines_selected); } -void Data::get_frequencies(Array1D<float>& frequencies, float image_size, +void Data::get_frequencies(aocommon::xt::Span<float, 1>& frequencies, + float image_size, unsigned int channel_offset) const { - auto nr_channels = frequencies.get_x_dim(); - auto max_uv = get_max_uv(); - float frequency_increment = SPEED_OF_LIGHT / (max_uv * image_size); - for (unsigned chan = 0; chan < nr_channels; chan++) { + const size_t nr_channels = frequencies.size(); + const float max_uv = get_max_uv(); + const float frequency_increment = SPEED_OF_LIGHT / (max_uv * image_size); + for (size_t chan = 0; chan < nr_channels; chan++) { frequencies(chan) = start_frequency + frequency_increment * (chan + channel_offset); } } -Array2D<UVW<float>> Data::get_uvw(unsigned int nr_baselines, - unsigned int nr_timesteps, - unsigned int baseline_offset, - unsigned int time_offset, - float integration_time) const { - Array2D<UVW<float>> uvw(nr_baselines, nr_timesteps); - get_uvw(uvw, baseline_offset, time_offset, integration_time); - return uvw; -} - -void Data::get_uvw(Array2D<UVW<float>>& uvw, unsigned int baseline_offset, - unsigned int time_offset, float integration_time) const { - unsigned int nr_baselines_total = m_baselines.size(); - unsigned int nr_baselines = uvw.get_y_dim(); - unsigned int nr_timesteps = uvw.get_x_dim(); +void Data::get_uvw(aocommon::xt::Span<UVW<float>, 2>& uvw, + unsigned int baseline_offset, unsigned int time_offset, + float integration_time) const { + const size_t nr_baselines_total = m_baselines.size(); + const size_t nr_baselines = uvw.shape(0); + const size_t nr_timesteps = uvw.shape(1); if (baseline_offset + nr_baselines > nr_baselines_total) { - std::cerr << "Out-of-range baselines selected: "; + std::stringstream message; + message << "Out-of-range baselines selected: "; if (baseline_offset > 0) { - std::cerr << baseline_offset << " + " << nr_baselines; + message << baseline_offset << " + " << nr_baselines; } - std::cerr << nr_baselines << " > " << nr_baselines_total << std::endl; - nr_baselines = nr_baselines_total; + message << nr_baselines << " > " << nr_baselines_total << std::endl; + throw std::runtime_error(message.str()); } // Evaluate uvw per baseline diff --git a/idg-util/src/initialize/Data.h b/idg-util/src/initialize/Data.h index 147ed61a444239df803465fb31ad7b7c6411d176..4183f4f2d6605297808478c05e2f9e4dac8ff5ca 100644 --- a/idg-util/src/initialize/Data.h +++ b/idg-util/src/initialize/Data.h @@ -47,17 +47,11 @@ class Data { unsigned int get_nr_baselines() const { return m_baselines.size(); }; - void get_frequencies(Array1D<float>& frequencies, float image_size, - unsigned int channel_offset = 0) const; + void get_frequencies(aocommon::xt::Span<float, 1>& frequencies, + float image_size, unsigned int channel_offset = 0) const; - Array2D<UVW<float>> get_uvw(unsigned int nr_baselines, - unsigned int nr_timesteps, - unsigned int baseline_offset = 0, - unsigned int time_offset = 0, - float integration_time = 1.0f) const; - - void get_uvw(Array2D<UVW<float>>& uvw, unsigned int baseline_offset = 0, - unsigned int time_offset = 0, + void get_uvw(aocommon::xt::Span<UVW<float>, 2>& uvw, + unsigned int baseline_offset = 0, unsigned int time_offset = 0, float integration_time = 1.0f) const; float get_max_uv() const; diff --git a/idg-util/src/initialize/datac.h b/idg-util/src/initialize/datac.h index c7bb3bef79483583910dc6507d86c4a4f979e9b3..6381c317318099d41e30ad91a267cb0d59b4bbe0 100644 --- a/idg-util/src/initialize/datac.h +++ b/idg-util/src/initialize/datac.h @@ -41,15 +41,18 @@ float DATA_get_nr_baselines(idg::Data* data) { void DATA_get_frequencies(idg::Data* data, void* ptr, unsigned int nr_channels, float image_size, unsigned int channel_offset) { - idg::Array1D<float> frequencies((float*)ptr, nr_channels); + const std::array<size_t, 1> frequencies_shape{nr_channels}; + auto frequencies = aocommon::xt::CreateSpan(reinterpret_cast<float*>(ptr), + frequencies_shape); data->get_frequencies(frequencies, image_size, channel_offset); } void DATA_get_uvw(idg::Data* data, void* ptr, unsigned int nr_baselines, unsigned int nr_timesteps, unsigned int baseline_offset, unsigned int time_offset, float integration_time) { - idg::Array2D<idg::UVW<float>> uvw((idg::UVW<float>*)ptr, nr_baselines, - nr_timesteps); + const std::array<size_t, 2> uvw_shape{nr_baselines, nr_timesteps}; + auto uvw = aocommon::xt::CreateSpan(reinterpret_cast<idg::UVW<float>*>(ptr), + uvw_shape); data->get_uvw(uvw, baseline_offset, time_offset, integration_time); } diff --git a/idg-util/src/initialize/init.cpp b/idg-util/src/initialize/init.cpp index 83a4e713c1f181e8bafd450d66187cecbb0d106a..ee169f3e4e1c7d186f7535bd4aee81173325b368 100644 --- a/idg-util/src/initialize/init.cpp +++ b/idg-util/src/initialize/init.cpp @@ -3,8 +3,8 @@ #include "init.h" -namespace idg { - +#include <xtensor/xview.hpp> +namespace { // Function to compute spheroidal. Based on reference code by BvdT. float evaluate_spheroidal(float nu) { float P[2][5] = { @@ -47,341 +47,176 @@ float evaluate_spheroidal(float nu) { return (1.0 - nusq) * (top / bot); } } - -// TODO: make generic, not spheroidal specific -// TODO: use real-to-complex and complex-to-real FFT -void resize_spheroidal(float* __restrict__ spheroidal_in, unsigned int size_in, - float* __restrict__ spheroidal_out, - unsigned int size_out) { - auto in_ft = new std::complex<float>[size_in * size_in]; - auto out_ft = new std::complex<float>[size_out * size_out]; - - for (unsigned i = 0; i < size_in; i++) { - for (unsigned j = 0; j < size_in; j++) { - in_ft[i * size_in + j] = spheroidal_in[i * size_in + j]; - } - } - idg::fft2f(size_in, in_ft); - - int offset = int((size_out - size_in) / 2); - - for (unsigned i = 0; i < size_in; i++) { - for (unsigned j = 0; j < size_in; j++) { - out_ft[(i + offset) * size_out + (j + offset)] = in_ft[i * size_in + j]; - } - } - idg::ifft2f(size_out, out_ft); - - float s = 1.0f / (size_in * size_in); - for (unsigned i = 0; i < size_out; i++) { - for (unsigned j = 0; j < size_out; j++) { - spheroidal_out[i * size_out + j] = out_ft[i * size_out + j].real() * s; - } - } - - delete[] in_ft; - delete[] out_ft; -} - -void init_example_aterms(Array4D<Matrix2x2<std::complex<float>>>& aterms) { - unsigned int nr_timeslots = aterms.get_w_dim(); - unsigned int nr_stations = aterms.get_z_dim(); - unsigned int height = aterms.get_y_dim(); - unsigned int width = aterms.get_x_dim(); - - for (unsigned t = 0; t < nr_timeslots; t++) { - for (unsigned ant = 0; ant < nr_stations; ant++) { - for (unsigned y = 0; y < height; y++) { - for (unsigned x = 0; x < width; x++) { - float scale = ((float)(t + 1) / nr_timeslots); - std::complex<float> valueXX = std::complex<float>(scale * 1.0, 1.1); - std::complex<float> valueXY = std::complex<float>(scale * 0.8, 0.9); - std::complex<float> valueYX = std::complex<float>(scale * 0.6, 1.7); - std::complex<float> valueYY = std::complex<float>(scale * 0.4, 0.5); - const Matrix2x2<std::complex<float>> aterm = {valueXX, valueXY, - valueYX, valueYY}; - aterms(t, ant, y, x) = aterm; - } - } - } - } -} +} // namespace +namespace idg { /* * Memory-allocation is handled by Proxy */ -Array1D<float> get_example_frequencies(proxy::Proxy& proxy, - unsigned int nr_channels, - float start_frequency, - float frequency_increment) { - using T = float; - Array1D<T> frequencies = proxy.allocate_array1d<T>(nr_channels); - - for (unsigned chan = 0; chan < nr_channels; chan++) { - frequencies(chan) = start_frequency + frequency_increment * chan; - } - +aocommon::xt::Span<float, 1> get_example_frequencies( + proxy::Proxy& proxy, unsigned int nr_channels, float start_frequency, + float frequency_increment) { + auto frequencies = proxy.allocate_span<float, 1>({nr_channels}); + init_example_frequencies(frequencies, start_frequency, frequency_increment); return frequencies; } -Array4D<std::complex<float>> get_dummy_visibilities( +aocommon::xt::Span<std::complex<float>, 4> get_dummy_visibilities( proxy::Proxy& proxy, unsigned int nr_baselines, unsigned int nr_timesteps, unsigned int nr_channels, unsigned int nr_correlations) { assert(nr_correlations == 2 || nr_correlations == 4); - - Array4D<std::complex<float>> visibilities = - proxy.allocate_array4d<std::complex<float>>(nr_baselines, nr_timesteps, - nr_channels, nr_correlations); - -// Set all visibilities -#pragma omp parallel for - for (unsigned bl = 0; bl < nr_baselines; bl++) { - for (unsigned time = 0; time < nr_timesteps; time++) { - for (unsigned chan = 0; chan < nr_channels; chan++) { - if (nr_correlations == 2) { - visibilities(bl, time, chan, 0) = 1.0f; - visibilities(bl, time, chan, 1) = 1.0f; - } else if (nr_correlations == 4) { - visibilities(bl, time, chan, 0) = 1.0f; - visibilities(bl, time, chan, 1) = 0.0f; - visibilities(bl, time, chan, 2) = 0.0f; - visibilities(bl, time, chan, 3) = 1.0f; - } - } - } - } - + auto visibilities = proxy.allocate_span<std::complex<float>, 4>( + {nr_baselines, nr_timesteps, nr_channels, nr_correlations}); + init_dummy_visibilities(visibilities); return visibilities; } -Array4D<std::complex<float>> get_example_visibilities( - proxy::Proxy& proxy, Array2D<UVW<float>>& uvw, Array1D<float>& frequencies, - float image_size, unsigned int nr_correlations, unsigned int grid_size, - unsigned int nr_point_sources, int max_pixel_offset, +aocommon::xt::Span<std::complex<float>, 4> get_example_visibilities( + proxy::Proxy& proxy, aocommon::xt::Span<UVW<float>, 2>& uvw, + aocommon::xt::Span<float, 1>& frequencies, float image_size, + unsigned int nr_correlations, unsigned int grid_size, + unsigned int nr_point_sources, unsigned int max_pixel_offset, unsigned int random_seed, float amplitude) { - unsigned int nr_baselines = uvw.get_y_dim(); - unsigned int nr_timesteps = uvw.get_x_dim(); - unsigned int nr_channels = frequencies.get_x_dim(); - - Array4D<std::complex<float>> visibilities = - proxy.allocate_array4d<std::complex<float>>(nr_baselines, nr_timesteps, - nr_channels, nr_correlations); - - if (max_pixel_offset == -1) { - max_pixel_offset = grid_size / 2; - } - - srand(random_seed); - - for (unsigned i = 0; i < nr_point_sources; i++) { - float x_offset = static_cast<float>(random()) / RAND_MAX; - float y_offset = static_cast<float>(random()) / RAND_MAX; - x_offset = (x_offset * (max_pixel_offset)) - (max_pixel_offset / 2); - y_offset = (y_offset * (max_pixel_offset)) - (max_pixel_offset / 2); - - add_pt_src(visibilities, uvw, frequencies, image_size, grid_size, x_offset, - y_offset, amplitude); - } - + const size_t nr_baselines = uvw.shape(0); + const size_t nr_timesteps = uvw.shape(1); + const size_t nr_channels = frequencies.shape(0); + auto visibilities = proxy.allocate_span<std::complex<float>, 4>( + {nr_baselines, nr_timesteps, nr_channels, nr_correlations}); + init_example_visibilities(visibilities, uvw, frequencies, image_size, + grid_size, nr_point_sources, max_pixel_offset, + random_seed, amplitude); return visibilities; } -Array1D<std::pair<unsigned int, unsigned int>> get_example_baselines( - proxy::Proxy& proxy, unsigned int nr_stations, unsigned int nr_baselines) { +aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1> +get_example_baselines(proxy::Proxy& proxy, unsigned int nr_stations, + unsigned int nr_baselines) { using T = std::pair<unsigned int, unsigned int>; - Array1D<T> baselines = proxy.allocate_array1d<T>(nr_baselines); - - unsigned bl = 0; - - for (unsigned station1 = 0; station1 < nr_stations; station1++) { - for (unsigned station2 = station1 + 1; station2 < nr_stations; station2++) { - if (bl >= nr_baselines) { - break; - } - baselines(bl) = std::pair<unsigned int, unsigned int>(station1, station2); - bl++; - } - } - + auto baselines = proxy.allocate_span<T, 1>({nr_baselines}); + init_example_baselines(baselines, nr_stations); return baselines; } -Array4D<Matrix2x2<std::complex<float>>> get_identity_aterms( +aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4> get_identity_aterms( proxy::Proxy& proxy, unsigned int nr_timeslots, unsigned int nr_stations, unsigned int height, unsigned int width) { using T = Matrix2x2<std::complex<float>>; - Array4D<T> aterms = - proxy.allocate_array4d<T>(nr_timeslots, nr_stations, height, width); - - for (unsigned t = 0; t < nr_timeslots; t++) { - for (unsigned ant = 0; ant < nr_stations; ant++) { - for (unsigned y = 0; y < height; y++) { - for (unsigned x = 0; x < width; x++) { - std::complex<float> valueXX = std::complex<float>(1.0, 0.0); - std::complex<float> valueXY = std::complex<float>(0.0, 0.0); - std::complex<float> valueYX = std::complex<float>(0.0, 0.0); - std::complex<float> valueYY = std::complex<float>(1.0, 0.0); - const Matrix2x2<std::complex<float>> aterm = {valueXX, valueXY, - valueYX, valueYY}; - aterms(t, ant, y, x) = aterm; - } - } - } - } - + auto aterms = + proxy.allocate_span<T, 4>({nr_timeslots, nr_stations, height, width}); + init_identity_aterms(aterms); return aterms; } -Array4D<Matrix2x2<std::complex<float>>> get_example_aterms( +aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4> get_example_aterms( proxy::Proxy& proxy, unsigned int nr_timeslots, unsigned int nr_stations, unsigned int height, unsigned int width) { using T = Matrix2x2<std::complex<float>>; - Array4D<T> aterms = - proxy.allocate_array4d<T>(nr_timeslots, nr_stations, height, width); - - for (unsigned t = 0; t < nr_timeslots; t++) { - for (unsigned ant = 0; ant < nr_stations; ant++) { - for (unsigned y = 0; y < height; y++) { - for (unsigned x = 0; x < width; x++) { - float scale = ((float)(t + 1) / nr_timeslots); - std::complex<float> valueXX = std::complex<float>(scale * 1.0, 1.1); - std::complex<float> valueXY = std::complex<float>(scale * 0.8, 0.9); - std::complex<float> valueYX = std::complex<float>(scale * 0.6, 1.7); - std::complex<float> valueYY = std::complex<float>(scale * 0.4, 0.5); - const Matrix2x2<std::complex<float>> aterm = {valueXX, valueXY, - valueYX, valueYY}; - aterms(t, ant, y, x) = aterm; - } - } - } - } - + auto aterms = + proxy.allocate_span<T, 4>({nr_timeslots, nr_stations, height, width}); + init_example_aterms(aterms); return aterms; } -Array1D<unsigned int> get_example_aterm_offsets(proxy::Proxy& proxy, - unsigned int nr_timeslots, - unsigned int nr_timesteps) { +aocommon::xt::Span<unsigned int, 1> get_example_aterm_offsets( + proxy::Proxy& proxy, unsigned int nr_timeslots, unsigned int nr_timesteps) { using T = unsigned int; - Array1D<T> aterm_offsets = proxy.allocate_array1d<T>(nr_timeslots + 1); - - for (unsigned time = 0; time < nr_timeslots; time++) { - aterm_offsets(time) = time * (nr_timesteps / nr_timeslots); - } - - aterm_offsets(nr_timeslots) = nr_timesteps; - + auto aterm_offsets = proxy.allocate_span<T, 1>({nr_timeslots + 1}); + init_example_aterm_offsets(aterm_offsets, nr_timesteps); return aterm_offsets; } -Array2D<float> get_example_spheroidal(proxy::Proxy& proxy, unsigned int height, - unsigned int width) { +aocommon::xt::Span<float, 2> get_identity_spheroidal(proxy::Proxy& proxy, + unsigned int height, + unsigned int width) { using T = float; - Array2D<T> spheroidal = proxy.allocate_array2d<T>(height, width); - - // Evaluate rows - float y[height]; - for (unsigned i = 0; i < height; i++) { - float tmp = fabs(-1 + i * 2.0f / float(height)); - y[i] = evaluate_spheroidal(tmp); - } - - // Evaluate columns - float x[width]; - for (unsigned i = 0; i < width; i++) { - float tmp = fabs(-1 + i * 2.0f / float(width)); - x[i] = evaluate_spheroidal(tmp); - } - - // Set values - for (unsigned i = 0; i < height; i++) { - for (unsigned j = 0; j < width; j++) { - spheroidal(i, j) = y[i] * x[j]; - } - } + auto spheroidal = proxy.allocate_span<T, 2>({height, width}); + init_identity_spheroidal(spheroidal); + return spheroidal; +} +aocommon::xt::Span<float, 2> get_example_spheroidal(proxy::Proxy& proxy, + unsigned int height, + unsigned int width) { + using T = float; + auto spheroidal = proxy.allocate_span<T, 2>({height, width}); + init_example_spheroidal(spheroidal); return spheroidal; } /* * Default memory allocation */ -Array1D<float> get_example_frequencies(unsigned int nr_channels, - float start_frequency, - float frequency_increment) { - Array1D<float> frequencies(nr_channels); +void init_example_frequencies(aocommon::xt::Span<float, 1>& frequencies, + float start_frequency, + float frequency_increment) { + const size_t nr_channels = frequencies.size(); for (unsigned chan = 0; chan < nr_channels; chan++) { frequencies(chan) = start_frequency + frequency_increment * chan; } - - return frequencies; } -Array4D<std::complex<float>> get_dummy_visibilities( - unsigned int nr_baselines, unsigned int nr_timesteps, - unsigned int nr_channels, unsigned int nr_correlations) { +void init_example_visibilities( + aocommon::xt::Span<std::complex<float>, 4>& visibilities, + aocommon::xt::Span<UVW<float>, 2>& uvw, + aocommon::xt::Span<float, 1>& frequencies, float image_size, + unsigned int grid_size, unsigned int nr_point_sources, + unsigned int max_pixel_offset, unsigned int random_seed, float amplitude) { + const size_t nr_baselines = visibilities.shape(0); + const size_t nr_timesteps = visibilities.shape(1); + const size_t nr_channels = visibilities.shape(2); + const size_t nr_correlations = visibilities.shape(3); assert(nr_correlations == 2 || nr_correlations == 4); + assert(uvw.shape(0) == nr_baselines); + assert(uvw.shape(1) == nr_timesteps); + assert(frequencies.size() == nr_channels); - Array4D<std::complex<float>> visibilities(nr_baselines, nr_timesteps, - nr_channels, nr_correlations); - -// Set all visibilities -#pragma omp parallel for - for (unsigned bl = 0; bl < nr_baselines; bl++) { - for (unsigned time = 0; time < nr_timesteps; time++) { - for (unsigned chan = 0; chan < nr_channels; chan++) { - if (nr_correlations == 2) { - visibilities(bl, time, chan, 0) = 1.0f; - visibilities(bl, time, chan, 1) = 1.0f; - } else if (nr_correlations == 4) { - visibilities(bl, time, chan, 0) = 1.0f; - visibilities(bl, time, chan, 1) = 0.0f; - visibilities(bl, time, chan, 2) = 0.0f; - visibilities(bl, time, chan, 3) = 1.0f; - } - } - } + if (max_pixel_offset == 0) { + max_pixel_offset = grid_size / 2; } - return visibilities; -} - -Array4D<std::complex<float>> get_example_visibilities( - Array2D<UVW<float>>& uvw, Array1D<float>& frequencies, float image_size, - unsigned int grid_size, unsigned int nr_correlations, - unsigned int nr_point_sources, unsigned int max_pixel_offset, - unsigned int random_seed, float amplitude) { - unsigned int nr_baselines = uvw.get_y_dim(); - unsigned int nr_timesteps = uvw.get_x_dim(); - unsigned int nr_channels = frequencies.get_x_dim(); - - Array4D<std::complex<float>> visibilities(nr_baselines, nr_timesteps, - nr_channels, nr_correlations); - std::fill_n(visibilities.data(), visibilities.size(), - std::complex<float>{0.0, 0.0}); - srand(random_seed); - for (unsigned i = 0; i < nr_point_sources; i++) { - float x_offset = (random() * (max_pixel_offset)) - (max_pixel_offset / 2); - float y_offset = (random() * (max_pixel_offset)) - (max_pixel_offset / 2); + for (size_t i = 0; i < nr_point_sources; i++) { + float x_offset = static_cast<float>(random()) / RAND_MAX; + float y_offset = static_cast<float>(random()) / RAND_MAX; + x_offset = (x_offset * (max_pixel_offset)) - (max_pixel_offset / 2); + y_offset = (y_offset * (max_pixel_offset)) - (max_pixel_offset / 2); add_pt_src(visibilities, uvw, frequencies, image_size, grid_size, x_offset, y_offset, amplitude); } +} - return visibilities; +void init_dummy_visibilities( + aocommon::xt::Span<std::complex<float>, 4>& visibilities) { + const size_t nr_baselines = visibilities.shape(0); + const size_t nr_correlations = visibilities.shape(3); + assert(nr_correlations == 2 || nr_correlations == 4); + +// Set all visibilities +#pragma omp parallel for + for (size_t bl = 0; bl < nr_baselines; bl++) { + if (nr_correlations == 2) { + xt::view(visibilities, bl, xt::all(), xt::all(), xt::all()) = 1.0f; + } else if (nr_correlations == 4) { + xt::view(visibilities, bl, xt::all(), xt::all(), 0) = 1.0f; + xt::view(visibilities, bl, xt::all(), xt::all(), 1) = 0.0f; + xt::view(visibilities, bl, xt::all(), xt::all(), 2) = 0.0f; + xt::view(visibilities, bl, xt::all(), xt::all(), 3) = 1.0f; + } + } } -Array1D<std::pair<unsigned int, unsigned int>> get_example_baselines( +xt::xtensor<std::pair<unsigned int, unsigned int>, 1> get_example_baselines( unsigned int nr_stations, unsigned int nr_baselines) { - Array1D<std::pair<unsigned int, unsigned int>> baselines(nr_baselines); + const std::array<size_t, 1> shape{nr_baselines}; + xt::xtensor<std::pair<unsigned int, unsigned int>, 1> baselines(shape); - unsigned bl = 0; + size_t bl = 0; - for (unsigned station1 = 0; station1 < nr_stations; station1++) { - for (unsigned station2 = station1 + 1; station2 < nr_stations; station2++) { + for (size_t station1 = 0; station1 < nr_stations; station1++) { + for (size_t station2 = station1 + 1; station2 < nr_stations; station2++) { if (bl >= nr_baselines) { break; } @@ -400,7 +235,7 @@ Data get_example_data(unsigned int max_nr_baselines, unsigned int grid_size, Data data(layout_file); // Determine the max baseline length for given grid_size - float max_uv = data.compute_max_uv(grid_size, nr_channels); + const float max_uv = data.compute_max_uv(grid_size, nr_channels); // Select only baselines up to max_uv meters long data.limit_max_baseline_length(max_uv); @@ -412,122 +247,115 @@ Data get_example_data(unsigned int max_nr_baselines, unsigned int grid_size, return data; } -Array4D<Matrix2x2<std::complex<float>>> get_identity_aterms( - unsigned int nr_timeslots, unsigned int nr_stations, unsigned int height, - unsigned int width) { - Array4D<Matrix2x2<std::complex<float>>> aterms(nr_timeslots, nr_stations, - height, width); - const Matrix2x2<std::complex<float>> aterm = {1.0f, 0.0f, 0.0f, 1.0f}; - - for (unsigned t = 0; t < nr_timeslots; t++) { - for (unsigned ant = 0; ant < nr_stations; ant++) { - for (unsigned y = 0; y < height; y++) { - for (unsigned x = 0; x < width; x++) { - aterms(t, ant, y, x) = aterm; - } +void add_pt_src(aocommon::xt::Span<std::complex<float>, 4>& visibilities, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<float, 1>& frequencies, + float image_size, unsigned int grid_size, float offset_x, + float offset_y, float amplitude) { + const size_t nr_baselines = visibilities.shape(0); + const size_t nr_timesteps = visibilities.shape(1); + const size_t nr_channels = visibilities.shape(2); + + const float l = offset_x * image_size / grid_size; + const float m = offset_y * image_size / grid_size; + + for (size_t bl = 0; bl < nr_baselines; bl++) { + for (size_t t = 0; t < nr_timesteps; t++) { + for (size_t c = 0; c < nr_channels; c++) { + const double speed_of_light = 299792458.0; + const float u = (frequencies(c) / speed_of_light) * uvw(bl, t).u; + const float v = (frequencies(c) / speed_of_light) * uvw(bl, t).v; + const std::complex<float> value = + amplitude * + std::exp(std::complex<float>(0, -2 * M_PI * (u * l + v * m))); + xt::view(visibilities, bl, t, c, xt::all()) += value; } } } +} - return aterms; +void init_identity_aterms( + aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4>& aterms) { + const std::complex<float> valueXX{1.0f, 0.0f}; + const std::complex<float> valueXY{0.0f, 0.0f}; + const std::complex<float> valueYX{0.0f, 0.0f}; + const std::complex<float> valueYY{1.0f, 0.0f}; + const Matrix2x2<std::complex<float>> aterm{valueXX, valueXY, valueYX, + valueYY}; + aterms.fill(aterm); } -Array4D<Matrix2x2<std::complex<float>>> get_example_aterms( - unsigned int nr_timeslots, unsigned int nr_stations, unsigned int height, - unsigned int width) { - assert(height == width); - Array4D<Matrix2x2<std::complex<float>>> aterms(nr_timeslots, nr_stations, - height, width); - init_example_aterms(aterms); - return aterms; +void init_example_aterms( + aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4>& aterms) { + const size_t nr_timeslots = aterms.shape(0); + + for (size_t t = 0; t < nr_timeslots; t++) { + const float scale = ((float)(t + 1) / nr_timeslots); + std::complex<float> valueXX{scale * 1.0f, 1.1f}; + std::complex<float> valueXY{scale * 0.8f, 0.9f}; + std::complex<float> valueYX{scale * 0.6f, 1.7f}; + std::complex<float> valueYY{scale * 0.4f, 0.5f}; + const Matrix2x2<std::complex<float>> aterm{valueXX, valueXY, valueYX, + valueYY}; + xt::view(aterms, t, xt::all(), xt::all(), xt::all()) = aterm; + } } -Array1D<unsigned int> get_example_aterm_offsets(unsigned int nr_timeslots, - unsigned int nr_timesteps) { - Array1D<unsigned int> aterm_offsets(nr_timeslots + 1); +void init_example_aterm_offsets( + aocommon::xt::Span<unsigned int, 1>& aterm_offsets, + unsigned int nr_timesteps) { + const size_t nr_timeslots = aterm_offsets.shape(0) - 1; - for (unsigned time = 0; time < nr_timeslots; time++) { + for (size_t time = 0; time < nr_timeslots; time++) { aterm_offsets(time) = time * (nr_timesteps / nr_timeslots); } aterm_offsets(nr_timeslots) = nr_timesteps; - - return aterm_offsets; } -Array2D<float> get_identity_spheroidal(unsigned int height, - unsigned int width) { - Array2D<float> spheroidal(height, width); - - float value = 1.0; - - for (unsigned y = 0; y < height; y++) { - for (unsigned x = 0; x < width; x++) { - spheroidal(y, x) = value; - } - } - - return spheroidal; +void init_identity_spheroidal(aocommon::xt::Span<float, 2>& spheroidal) { + spheroidal.fill(1.0f); } -Array2D<float> get_example_spheroidal(unsigned int height, unsigned int width) { - Array2D<float> spheroidal(height, width); +void init_example_spheroidal(aocommon::xt::Span<float, 2>& spheroidal) { + const size_t height = spheroidal.shape(0); + const size_t width = spheroidal.shape(1); // Evaluate rows float y[height]; for (unsigned i = 0; i < height; i++) { float tmp = fabs(-1 + i * 2.0f / float(height)); - y[i] = evaluate_spheroidal(tmp); + y[i] = ::evaluate_spheroidal(tmp); } // Evaluate columns float x[width]; for (unsigned i = 0; i < width; i++) { float tmp = fabs(-1 + i * 2.0f / float(width)); - x[i] = evaluate_spheroidal(tmp); + x[i] = ::evaluate_spheroidal(tmp); } // Set values - for (unsigned i = 0; i < height; i++) { - for (unsigned j = 0; j < width; j++) { + for (size_t i = 0; i < height; i++) { + for (size_t j = 0; j < width; j++) { spheroidal(i, j) = y[i] * x[j]; } } - - return spheroidal; } -Array1D<float> get_zero_shift() { - Array1D<float> shift(2); - shift.zero(); - return shift; -} +void init_example_baselines( + aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& baselines, + unsigned int nr_stations) { + const size_t nr_baselines = baselines.size(); + size_t bl = 0; -void add_pt_src(Array4D<std::complex<float>>& visibilities, - Array2D<UVW<float>>& uvw, Array1D<float>& frequencies, - float image_size, unsigned int grid_size, float offset_x, - float offset_y, float amplitude) { - auto nr_baselines = visibilities.get_w_dim(); - auto nr_timesteps = visibilities.get_z_dim(); - auto nr_channels = visibilities.get_y_dim(); - auto nr_correlations = visibilities.get_x_dim(); - - float l = offset_x * image_size / grid_size; - float m = offset_y * image_size / grid_size; - - for (unsigned bl = 0; bl < nr_baselines; bl++) { - for (unsigned t = 0; t < nr_timesteps; t++) { - for (unsigned c = 0; c < nr_channels; c++) { - const double speed_of_light = 299792458.0; - float u = (frequencies(c) / speed_of_light) * uvw(bl, t).u; - float v = (frequencies(c) / speed_of_light) * uvw(bl, t).v; - std::complex<float> value = - amplitude * - exp(std::complex<float>(0, -2 * M_PI * (u * l + v * m))); - for (unsigned cor = 0; cor < nr_correlations; cor++) { - visibilities(bl, t, c, cor) += value; - } + for (size_t station1 = 0; station1 < nr_stations; station1++) { + for (size_t station2 = station1 + 1; station2 < nr_stations; station2++) { + if (bl >= nr_baselines) { + break; } + baselines(bl) = std::pair<unsigned int, unsigned int>(station1, station2); + bl++; } } } diff --git a/idg-util/src/initialize/init.h b/idg-util/src/initialize/init.h index c92edba57251ca81f53f1c913627e0880c86f1cf..936b89417121ddbbc1cade64573c49970eaed60f 100644 --- a/idg-util/src/initialize/init.h +++ b/idg-util/src/initialize/init.h @@ -21,83 +21,103 @@ Data get_example_data(unsigned int max_nr_baselines, unsigned int grid_size, /* * Memory-allocation is handled by Proxy */ -Array1D<float> get_example_frequencies( +aocommon::xt::Span<float, 1> get_example_frequencies( proxy::Proxy& proxy, unsigned int nr_channels, float start_frequency = Data::start_frequency, float frequency_increment = Data::frequency_increment); -Array4D<std::complex<float>> get_dummy_visibilities( +aocommon::xt::Span<std::complex<float>, 4> get_dummy_visibilities( proxy::Proxy& proxy, unsigned int nr_baselines, unsigned int nr_timesteps, unsigned int nr_channels, unsigned int nr_correlations); -Array4D<std::complex<float>> get_example_visibilities( - proxy::Proxy& proxy, Array2D<UVW<float>>& uvw, Array1D<float>& frequencies, - float image_size, unsigned int nr_correlations, unsigned int grid_size, - unsigned int nr_polarizations, unsigned int nr_point_sources = 4, - unsigned int max_pixel_offset = -1, unsigned int random_seed = 2, - float amplitude = 1); +aocommon::xt::Span<std::complex<float>, 4> get_example_visibilities( + proxy::Proxy& proxy, aocommon::xt::Span<UVW<float>, 2>& uvw, + aocommon::xt::Span<float, 1>& frequencies, float image_size, + unsigned int nr_correlations, unsigned int grid_size, + unsigned int nr_point_sources = 4, unsigned int max_pixel_offset = 0, + unsigned int random_seed = 2, float amplitude = 1); -Array1D<std::pair<unsigned int, unsigned int>> get_example_baselines( - proxy::Proxy& proxy, unsigned int nr_stations, unsigned int nr_baselines); +aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1> +get_example_baselines(proxy::Proxy& proxy, unsigned int nr_stations, + unsigned int nr_baselines); -Array4D<Matrix2x2<std::complex<float>>> get_identity_aterms( +aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4> get_identity_aterms( proxy::Proxy& proxy, unsigned int nr_timeslots, unsigned int nr_stations, unsigned int height, unsigned int width); -Array4D<Matrix2x2<std::complex<float>>> get_example_aterms( +aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4> get_example_aterms( proxy::Proxy& proxy, unsigned int nr_timeslots, unsigned int nr_stations, unsigned int height, unsigned int width); -Array1D<unsigned int> get_example_aterm_offsets(proxy::Proxy& proxy, - unsigned int nr_timeslots, - unsigned int nr_timesteps); +aocommon::xt::Span<unsigned int, 1> get_example_aterm_offsets( + proxy::Proxy& proxy, unsigned int nr_timeslots, unsigned int nr_timesteps); -Array2D<float> get_example_spheroidal(proxy::Proxy& proxy, unsigned int height, - unsigned int width); +aocommon::xt::Span<float, 2> get_identity_spheroidal(proxy::Proxy& proxy, + unsigned int height, + unsigned int width); -Array1D<float> get_zero_shift(); +aocommon::xt::Span<float, 2> get_example_spheroidal(proxy::Proxy& proxy, + unsigned int height, + unsigned int width); /* * Default memory allocation */ -Array1D<float> get_example_frequencies( - unsigned int nr_channels, float start_frequency = Data::start_frequency, +void init_example_frequencies( + aocommon::xt::Span<float, 1>& frequencies, + float start_frequency = Data::start_frequency, float frequency_increment = Data::frequency_increment); -Array4D<std::complex<float>> get_dummy_visibilities( - unsigned int nr_baselines, unsigned int nr_timesteps, - unsigned int nr_channels, unsigned int nr_correlations); +void init_example_visibilities( + aocommon::xt::Span<std::complex<float>, 4>& visibilities, + aocommon::xt::Span<UVW<float>, 2>& uvw, + aocommon::xt::Span<float, 1>& frequencies, float image_size, + unsigned int grid_size, unsigned int nr_point_sources = 4, + unsigned int max_pixel_offset = 0, unsigned int random_seed = 2, + float amplitude = 1); -Array4D<std::complex<float>> get_example_visibilities( - Array2D<UVW<float>>& uvw, Array1D<float>& frequencies, float image_size, - unsigned int grid_size, unsigned int nr_correlations, - unsigned int nr_point_sources = 4, unsigned int max_pixel_offset = -1, - unsigned int random_seed = 2, float amplitude = 1); +void init_dummy_visibilities( + aocommon::xt::Span<std::complex<float>, 4>& visibilities); -Array1D<std::pair<unsigned int, unsigned int>> get_example_baselines( +xt::xtensor<std::pair<unsigned int, unsigned int>, 1> get_example_baselines( unsigned int nr_stations, unsigned int nr_baselines); -Array4D<Matrix2x2<std::complex<float>>> get_identity_aterms( +xt::xtensor<Matrix2x2<std::complex<float>>, 4> get_identity_aterms( unsigned int nr_timeslots, unsigned int nr_stations, unsigned int height, unsigned int width); -Array4D<Matrix2x2<std::complex<float>>> get_example_aterms( +xt::xtensor<Matrix2x2<std::complex<float>>, 4> get_example_aterms( unsigned int nr_timeslots, unsigned int nr_stations, unsigned int height, unsigned int width); -Array1D<unsigned int> get_example_aterm_offsets(unsigned int nr_timeslots, - unsigned int nr_timesteps); +xt::xtensor<unsigned int, 1> get_example_aterm_offsets( + unsigned int nr_timeslots, unsigned int nr_timesteps); -Array2D<float> get_identity_spheroidal(unsigned int height, unsigned int width); +void init_identity_spheroidal(aocommon::xt::Span<float, 2>& spheroidal); -Array2D<float> get_example_spheroidal(unsigned int height, unsigned int width); +void init_example_spheroidal(aocommon::xt::Span<float, 2>& spheroidal); float evaluate_spheroidal(float nu); -void add_pt_src(Array4D<std::complex<float>>& visibilities, - Array2D<UVW<float>>& uvw, Array1D<float>& frequencies, - float image_size, unsigned int grid_size, float x, float y, - float amplitude); +void add_pt_src(aocommon::xt::Span<std::complex<float>, 4>& visibilities, + const aocommon::xt::Span<UVW<float>, 2>& uvw, + const aocommon::xt::Span<float, 1>& frequencies, + float image_size, unsigned int grid_size, float offset_x, + float offset_y, float amplitude); + +void init_identity_aterms( + aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4>& aterms); + +void init_example_aterms( + aocommon::xt::Span<Matrix2x2<std::complex<float>>, 4>& aterms); + +void init_example_aterm_offsets( + aocommon::xt::Span<unsigned int, 1>& aterm_offsets, + unsigned int nr_timesteps); + +void init_example_baselines( + aocommon::xt::Span<std::pair<unsigned int, unsigned int>, 1>& baselines, + unsigned int nr_stations); } // namespace idg diff --git a/idg-util/src/initialize/initc.h b/idg-util/src/initialize/initc.h index c67119191e64eeabda644abe12bbeee3c489a0e8..3abca012bca9f122795ab8b55e384ba6380b3c50 100644 --- a/idg-util/src/initialize/initc.h +++ b/idg-util/src/initialize/initc.h @@ -4,72 +4,100 @@ extern "C" { void utils_init_identity_spheroidal(void* ptr, int subgrid_size) { - idg::Array2D<float> spheroidal = - idg::get_identity_spheroidal(subgrid_size, subgrid_size); - memcpy(ptr, spheroidal.data(), spheroidal.bytes()); + const std::array<size_t, 2> spheroidal_shape{ + static_cast<size_t>(subgrid_size), static_cast<size_t>(subgrid_size)}; + auto spheroidal = + aocommon::xt::CreateSpan(reinterpret_cast<float*>(ptr), spheroidal_shape); + idg::init_identity_spheroidal(spheroidal); } void utils_init_example_spheroidal(void* ptr, int subgrid_size) { - idg::Array2D<float> spheroidal = - idg::get_example_spheroidal(subgrid_size, subgrid_size); - memcpy(ptr, spheroidal.data(), spheroidal.bytes()); + const std::array<size_t, 2> spheroidal_shape{ + static_cast<size_t>(subgrid_size), static_cast<size_t>(subgrid_size)}; + auto spheroidal = + aocommon::xt::CreateSpan(reinterpret_cast<float*>(ptr), spheroidal_shape); + idg::init_example_spheroidal(spheroidal); } void utils_init_example_frequencies(void* ptr, int nr_channels) { - idg::Array1D<float> frequencies = idg::get_example_frequencies(nr_channels); - memcpy(ptr, frequencies.data(), frequencies.bytes()); + const std::array<size_t, 1> frequencies_shape{ + static_cast<size_t>(nr_channels)}; + auto frequencies = aocommon::xt::CreateSpan(reinterpret_cast<float*>(ptr), + frequencies_shape); + idg::init_example_frequencies(frequencies); } void utils_init_dummy_visibilities(void* ptr, int nr_baselines, int nr_timesteps, int nr_channels, int nr_correlations) { - idg::Array4D<std::complex<float>> visibilities = idg::get_dummy_visibilities( - nr_baselines, nr_timesteps, nr_channels, nr_correlations); - memcpy(ptr, visibilities.data(), visibilities.bytes()); + const std::array<size_t, 4> visibilities_shape{ + static_cast<size_t>(nr_baselines), static_cast<size_t>(nr_timesteps), + static_cast<size_t>(nr_channels), static_cast<size_t>(nr_correlations)}; + auto visibilities = aocommon::xt::CreateSpan( + reinterpret_cast<std::complex<float>*>(ptr), visibilities_shape); + idg::init_dummy_visibilities(visibilities); } void utils_add_pt_src(float x, float y, float amplitude, int nr_baselines, int nr_timesteps, int nr_channels, int nr_correlations, float image_size, int grid_size, void* uvw, void* frequencies, void* visibilities) { - typedef idg::UVW<float> UVWType; - idg::Array4D<std::complex<float>> visibilities_( - reinterpret_cast<std::complex<float>*>(visibilities), nr_baselines, - nr_timesteps, nr_channels, nr_correlations); - idg::Array2D<UVWType> uvw_((UVWType*)uvw, nr_baselines, nr_timesteps); - idg::Array1D<float> frequencies_((float*)frequencies, nr_channels); - idg::add_pt_src(visibilities_, uvw_, frequencies_, image_size, grid_size, x, - y, amplitude); + const std::array<size_t, 1> frequencies_shape{ + static_cast<size_t>(nr_channels)}; + auto frequencies_span = aocommon::xt::CreateSpan( + reinterpret_cast<float*>(frequencies), frequencies_shape); + const std::array<size_t, 2> uvw_shape{static_cast<size_t>(nr_baselines), + static_cast<size_t>(nr_timesteps)}; + auto uvw_span = aocommon::xt::CreateSpan( + reinterpret_cast<idg::UVW<float>*>(uvw), uvw_shape); + const std::array<size_t, 4> visibilities_shape{ + static_cast<size_t>(nr_baselines), static_cast<size_t>(nr_timesteps), + static_cast<size_t>(nr_channels), static_cast<size_t>(nr_correlations)}; + auto visibilities_span = aocommon::xt::CreateSpan( + reinterpret_cast<std::complex<float>*>(visibilities), visibilities_shape); + idg::add_pt_src(visibilities_span, uvw_span, frequencies_span, image_size, + grid_size, x, y, amplitude); } void utils_init_identity_aterms(void* ptr, int nr_timeslots, int nr_stations, int subgrid_size, int nr_correlations) { - idg::Array4D<idg::Matrix2x2<std::complex<float>>> aterms = - idg::get_identity_aterms(nr_timeslots, nr_stations, subgrid_size, - subgrid_size); - memcpy(ptr, aterms.data(), aterms.bytes()); + const std::array<size_t, 4> aterms_shape{ + static_cast<size_t>(nr_timeslots), static_cast<size_t>(nr_stations), + static_cast<size_t>(subgrid_size), static_cast<size_t>(subgrid_size)}; + using T = idg::Matrix2x2<std::complex<float>>; + auto aterms = + aocommon::xt::CreateSpan(reinterpret_cast<T*>(ptr), aterms_shape); + idg::init_identity_aterms(aterms); } void utils_init_example_aterms(void* ptr, int nr_timeslots, int nr_stations, int subgrid_size, int nr_correlations) { - idg::Array4D<idg::Matrix2x2<std::complex<float>>> aterms = - idg::get_example_aterms(nr_timeslots, nr_stations, subgrid_size, - subgrid_size); - memcpy(ptr, aterms.data(), aterms.bytes()); + const std::array<size_t, 4> aterms_shape{ + static_cast<size_t>(nr_timeslots), static_cast<size_t>(nr_stations), + static_cast<size_t>(subgrid_size), static_cast<size_t>(subgrid_size)}; + using Aterm = idg::Matrix2x2<std::complex<float>>; + auto aterms = + aocommon::xt::CreateSpan(reinterpret_cast<Aterm*>(ptr), aterms_shape); + idg::init_example_aterms(aterms); } void utils_init_example_aterm_offsets(void* ptr, int nr_timeslots, int nr_timesteps) { - idg::Array1D<unsigned int> aterm_offsets = - idg::get_example_aterm_offsets(nr_timeslots, nr_timesteps); - memcpy(ptr, aterm_offsets.data(), aterm_offsets.bytes()); + const std::array<size_t, 1> aterm_offsets_shape{ + static_cast<size_t>(nr_timeslots) + 1}; + auto aterm_offsets = aocommon::xt::CreateSpan( + reinterpret_cast<unsigned int*>(ptr), aterm_offsets_shape); + idg::init_example_aterm_offsets(aterm_offsets, nr_timesteps); } void utils_init_example_baselines(void* ptr, int nr_stations, int nr_baselines) { - idg::Array1D<std::pair<unsigned int, unsigned int>> baselines = - idg::get_example_baselines(nr_stations, nr_baselines); - memcpy(ptr, baselines.data(), baselines.bytes()); + const std::array<size_t, 1> baselines_shape{ + static_cast<size_t>(nr_baselines)}; + auto baselines = aocommon::xt::CreateSpan( + reinterpret_cast<std::pair<unsigned int, unsigned int>*>(ptr), + baselines_shape); + idg::init_example_baselines(baselines, nr_stations); } } // end extern "C" diff --git a/idg-util/src/python/util.py b/idg-util/src/python/util.py index 6daba72abe31e64ac37d5726f97b7a17cd7e840c..05efbd2d2dc4387b42eee0709517c80c9e74c1a7 100644 --- a/idg-util/src/python/util.py +++ b/idg-util/src/python/util.py @@ -18,31 +18,6 @@ from idg.idgtypes import * lib = ctypes.cdll.LoadLibrary('libidg-util.so') -def resize_spheroidal(spheroidal, size, dtype=np.float32): - """ - Resize a spheroidal - - :param spheroidal: Input spheroidal - :type spheroidal: np.arrayd(type=float) (two dimensions) - :param size: New size along one axis - :type size: int - :param dtype: new dtype, defaults to np.float32 - :type dtype: np.dtype, optional - :return: New spheroidal - :rtype: np.array(dtype=float) (two dimensions) - """ - if spheroidal.shape[1] != spheroidal.shape[0]: - raise ValueError("Input spheroidal size should be square") - subgrid_size = spheroidal.shape[0] - tmp = spheroidal.astype(np.float32) - result = np.zeros(shape=(size, size), dtype=np.float32) - lib.utils_resize_spheroidal(tmp.ctypes.data_as(ctypes.c_void_p), - ctypes.c_int(subgrid_size), - result.ctypes.data_as(ctypes.c_void_p), - ctypes.c_int(size)) - return result.astype(dtype) - - def nr_baselines_to_nr_stations(nr_baselines): """ Convert number of baselines to number of stations, assuming that all station