Array¶
The array is a simple concept over the data in oneDAL. It represents a storage that:
Holds the data allocated inside it or references to the external data. The data are organized as one homogeneous and contiguous memory block.
Contains information about the memory block’s size.
Supports both immutable and mutable data.
Provides an ability to change the data state from immutable to mutable one.
Holds ownership information on the data (see the data ownership requirements section).
Ownership information on the data can be shared between several arrays. It is possible to create a new array from another one without any data copies.
Usage Example¶
The following listing provides a brief introduction to the array API and an example of basic usage scenario:
#include <sycl/sycl.hpp>
#include <iostream>
#include <string>
#include "oneapi/dal/array.hpp"
using namespace oneapi;
void print_property(const std::string& description, const auto& property) {
std::cout << description << ": " << property << std::endl;
}
int main() {
sycl::queue queue { sycl::default_selector() };
constexpr std::int64_t data_count = 4;
const float data[] = { 1.0f, 2.0f, 3.0f, 4.0f };
// Creating an array from immutable user-defined memory
auto arr_data = dal::array<float>::wrap(data, data_count);
// Creating an array from internally allocated memory filled by ones
auto arr_ones = dal::array<float>::full(queue, data_count, 1.0f);
print_property("Is arr_data mutable", arr_data.has_mutable_data()); // false
print_property("Is arr_ones mutable", arr_ones.has_mutable_data()); // true
// Creating new array from arr_data without data copy - they share ownership information.
dal::array<float> arr_mdata = arr_data;
print_property("arr_mdata elements count", arr_mdata.get_count()); // equal to data_count
print_property("Is arr_mdata mutable", arr_mdata.has_mutable_data()); // false
/// Copying data inside arr_mdata to new mutable memory block.
/// arr_data still refers to the original data pointer.
arr_mdata.need_mutable_data(queue);
print_property("Is arr_data mutable", arr_data.has_mutable_data()); // false
print_property("Is arr_mdata mutable", arr_mdata.has_mutable_data()); // true
queue.submit([&](sycl::handler& cgh){
auto mdata = arr_mdata.get_mutable_data();
auto cones = arr_ones.get_data();
cgh.parallel_for<class array_addition>(sycl::range<1>(data_count), [=](sycl::id<1> idx) {
mdata[idx[0]] += cones[idx[0]];
});
}).wait();
std::cout << "arr_mdata values: ";
for(std::int64_t i = 0; i < arr_mdata.get_count(); i++) {
std::cout << arr_mdata[i] << ", ";
}
std::cout << std::endl;
return 0;
}
Data ownership requirements¶
The array supports the following requirements on the internal data management:
An array owns two properties representing raw pointers to the data:
data
for a pointer to immutable data blockmutable_data
for a pointer to mutable data block (see the api array)
If an array owns mutable data, both properties point to the same memory block.
If an array owns immutable data,
mutable_data
isnullptr
.An array stores the number of elements in the block it owns and updates the
count
property when a new memory block is assigned to the array.An array stores a pointer to the ownership structure of the data:
The reference count indicating how many array objects refer to the same memory block.
The deleter object used to free the memory block when reference count is zero.
An array creates the ownership structure for a new memory block not associated with such structure.
An array decrements the number of references to the memory block when the array goes out of the scope. If the number of references is zero, the array calls the deleter on this memory block and free the ownership structure.
An array stores the pointer to the ownership structure created by another array when they share the data. An array increments the reference count for it to be equal to the number of array objects sharing the same data.
Programming interface¶
Refer to API Reference: Array.