Related
I'm new to Vulkan and graphics programming. I'm using vulkano Rust library https://github.com/vulkano-rs/vulkano (v0.17).
I want to use a compute pipeline to calculate something on a large set of circles. Circles are described as an input tuple (x, y). 2048 of them at the moment. I will make a calculation on them and output 2048 booleans depending on the outcome.
I use one buffer for inputted circles, and the other buffer for the outputted booleans.
At first I just want to make the output to be all trues.
let data_in_iter = (0..2048).map(|i| (i, i));
let data_in_buffer =
CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), false, data_in_iter)
.expect("failed to create buffer");
let data_out_iter = (0..2048).map(|_| false);
let data_out_buffer =
CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), false, data_out_iter)
.expect("failed to create buffer");
let compute_pipeline = Arc::new({
mod cs {
vulkano_shaders::shader! {
ty: "compute",
src:
"
#version 450
layout(local_size_x = 1024, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 0) buffer DataIn {
uvec2 data[];
} buf_in;
layout(set = 0, binding = 1) buffer DataOut {
bool data[];
} buf_out;
void main() {
uint idx = gl_GlobalInvocationID.x;
buf_out.data[idx] = true /* buf_in.data[idx].x + buf_in.data[idx].y < 2048 */;
}
"
}
}
let shader = cs::Shader::load(device.clone()).expect("failed to create shader module");
ComputePipeline::new(device.clone(), &shader.main_entry_point(), &())
.expect("failed to create compute pipeline")
});
let layout = compute_pipeline.layout().descriptor_set_layout(0).unwrap();
let set = Arc::new(
PersistentDescriptorSet::start(layout.clone())
.add_buffer(data_in_buffer.clone())
.unwrap()
.add_buffer(data_out_buffer.clone())
.unwrap()
.build()
.unwrap(),
);
let command_buffer =
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
.unwrap()
.dispatch([2, 1, 1], compute_pipeline.clone(), set.clone(), ())
.unwrap()
.build()
.unwrap();
let future = sync::now(device.clone())
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_signal_fence_and_flush()
.unwrap();
future.wait(None).unwrap();
let content = data_out_buffer.read().unwrap();
for (n, val) in content.iter().enumerate() {
println!("{} {:?}", n, val);
}
But the output I get is:
0 true
1 false
2 false
3 false
4 true
5 false
6 false
7 false
8 true
9 false
...
2047 false
The default layout for storage buffers requires that each element of an array start at a 16-byte boundary. So what you're seeing is expected: buf_out.data[i] is written starting at byte 16*i in the output buffer.
You can either match that in your host code, or add the std430 modifier inside the layout() for DataOut. Note the same issue will affect DataIn.
I've got code that looks like this:
for (std::list<item*>::iterator i=items.begin();i!=items.end();i++)
{
bool isActive = (*i)->update();
//if (!isActive)
// items.remove(*i);
//else
other_code_involving(*i);
}
items.remove_if(CheckItemNotActive);
I'd like remove inactive items immediately after update them, inorder to avoid walking the list again. But if I add the commented-out lines, I get an error when I get to i++: "List iterator not incrementable". I tried some alternates which didn't increment in the for statement, but I couldn't get anything to work.
What's the best way to remove items as you are walking a std::list?
You have to increment the iterator first (with i++) and then remove the previous element (e.g., by using the returned value from i++). You can change the code to a while loop like so:
std::list<item*>::iterator i = items.begin();
while (i != items.end())
{
bool isActive = (*i)->update();
if (!isActive)
{
items.erase(i++); // alternatively, i = items.erase(i);
}
else
{
other_code_involving(*i);
++i;
}
}
You want to do:
i= items.erase(i);
That will correctly update the iterator to point to the location after the iterator you removed.
You need to do the combination of Kristo's answer and MSN's:
// Note: Using the pre-increment operator is preferred for iterators because
// there can be a performance gain.
//
// Note: As long as you are iterating from beginning to end, without inserting
// along the way you can safely save end once; otherwise get it at the
// top of each loop.
std::list< item * >::iterator iter = items.begin();
std::list< item * >::iterator end = items.end();
while (iter != end)
{
item * pItem = *iter;
if (pItem->update() == true)
{
other_code_involving(pItem);
++iter;
}
else
{
// BTW, who is deleting pItem, a.k.a. (*iter)?
iter = items.erase(iter);
}
}
Of course, the most efficient and SuperCool® STL savy thing would be something like this:
// This implementation of update executes other_code_involving(Item *) if
// this instance needs updating.
//
// This method returns true if this still needs future updates.
//
bool Item::update(void)
{
if (m_needsUpdates == true)
{
m_needsUpdates = other_code_involving(this);
}
return (m_needsUpdates);
}
// This call does everything the previous loop did!!! (Including the fact
// that it isn't deleting the items that are erased!)
items.remove_if(std::not1(std::mem_fun(&Item::update)));
I have sumup it, here is the three method with example:
1. using while loop
list<int> lst{4, 1, 2, 3, 5};
auto it = lst.begin();
while (it != lst.end()){
if((*it % 2) == 1){
it = lst.erase(it);// erase and go to next
} else{
++it; // go to next
}
}
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
2. using remove_if member funtion in list:
list<int> lst{4, 1, 2, 3, 5};
lst.remove_if([](int a){return a % 2 == 1;});
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
3. using std::remove_if funtion combining with erase member function:
list<int> lst{4, 1, 2, 3, 5};
lst.erase(std::remove_if(lst.begin(), lst.end(), [](int a){
return a % 2 == 1;
}), lst.end());
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
4. using for loop , should note update the iterator:
list<int> lst{4, 1, 2, 3, 5};
for(auto it = lst.begin(); it != lst.end();++it){
if ((*it % 2) == 1){
it = lst.erase(it); erase and go to next(erase will return the next iterator)
--it; // as it will be add again in for, so we go back one step
}
}
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
Use std::remove_if algorithm.
Edit:
Work with collections should be like:
prepare collection.
process collection.
Life will be easier if you won't mix this steps.
std::remove_if. or list::remove_if ( if you know that you work with list and not with the TCollection )
std::for_each
The alternative for loop version to Kristo's answer.
You lose some efficiency, you go backwards and then forward again when deleting but in exchange for the extra iterator increment you can have the iterator declared in the loop scope and the code looking a bit cleaner. What to choose depends on priorities of the moment.
The answer was totally out of time, I know...
typedef std::list<item*>::iterator item_iterator;
for(item_iterator i = items.begin(); i != items.end(); ++i)
{
bool isActive = (*i)->update();
if (!isActive)
{
items.erase(i--);
}
else
{
other_code_involving(*i);
}
}
Here's an example using a for loop that iterates the list and increments or revalidates the iterator in the event of an item being removed during traversal of the list.
for(auto i = items.begin(); i != items.end();)
{
if(bool isActive = (*i)->update())
{
other_code_involving(*i);
++i;
}
else
{
i = items.erase(i);
}
}
items.remove_if(CheckItemNotActive);
Removal invalidates only the iterators that point to the elements that are removed.
So in this case after removing *i , i is invalidated and you cannot do increment on it.
What you can do is first save the iterator of element that is to be removed , then increment the iterator and then remove the saved one.
If you think of the std::list like a queue, then you can dequeue and enqueue all the items that you want to keep, but only dequeue (and not enqueue) the item you want to remove. Here's an example where I want to remove 5 from a list containing the numbers 1-10...
std::list<int> myList;
int size = myList.size(); // The size needs to be saved to iterate through the whole thing
for (int i = 0; i < size; ++i)
{
int val = myList.back()
myList.pop_back() // dequeue
if (val != 5)
{
myList.push_front(val) // enqueue if not 5
}
}
myList will now only have numbers 1-4 and 6-10.
Iterating backwards avoids the effect of erasing an element on the remaining elements to be traversed:
typedef list<item*> list_t;
for ( list_t::iterator it = items.end() ; it != items.begin() ; ) {
--it;
bool remove = <determine whether to remove>
if ( remove ) {
items.erase( it );
}
}
PS: see this, e.g., regarding backward iteration.
PS2: I did not thoroughly tested if it handles well erasing elements at the ends.
You can write
std::list<item*>::iterator i = items.begin();
while (i != items.end())
{
bool isActive = (*i)->update();
if (!isActive) {
i = items.erase(i);
} else {
other_code_involving(*i);
i++;
}
}
You can write equivalent code with std::list::remove_if, which is less verbose and more explicit
items.remove_if([] (item*i) {
bool isActive = (*i)->update();
if (!isActive)
return true;
other_code_involving(*i);
return false;
});
The std::vector::erase std::remove_if idiom should be used when items is a vector instead of a list to keep compexity at O(n) - or in case you write generic code and items might be a container with no effective way to erase single items (like a vector)
items.erase(std::remove_if(begin(items), end(items), [] (item*i) {
bool isActive = (*i)->update();
if (!isActive)
return true;
other_code_involving(*i);
return false;
}));
do while loop, it's flexable and fast and easy to read and write.
auto textRegion = m_pdfTextRegions.begin();
while(textRegion != m_pdfTextRegions.end())
{
if ((*textRegion)->glyphs.empty())
{
m_pdfTextRegions.erase(textRegion);
textRegion = m_pdfTextRegions.begin();
}
else
textRegion++;
}
I'd like to share my method. This method also allows the insertion of the element to the back of the list during iteration
#include <iostream>
#include <list>
int main(int argc, char **argv) {
std::list<int> d;
for (int i = 0; i < 12; ++i) {
d.push_back(i);
}
auto it = d.begin();
int nelem = d.size(); // number of current elements
for (int ielem = 0; ielem < nelem; ++ielem) {
auto &i = *it;
if (i % 2 == 0) {
it = d.erase(it);
} else {
if (i % 3 == 0) {
d.push_back(3*i);
}
++it;
}
}
for (auto i : d) {
std::cout << i << ", ";
}
std::cout << std::endl;
// result should be: 1, 3, 5, 7, 9, 11, 9, 27,
return 0;
}
I think you have a bug there, I code this way:
for (std::list<CAudioChannel *>::iterator itAudioChannel = audioChannels.begin();
itAudioChannel != audioChannels.end(); )
{
CAudioChannel *audioChannel = *itAudioChannel;
std::list<CAudioChannel *>::iterator itCurrentAudioChannel = itAudioChannel;
itAudioChannel++;
if (audioChannel->destroyMe)
{
audioChannels.erase(itCurrentAudioChannel);
delete audioChannel;
continue;
}
audioChannel->Mix(outBuffer, numSamples);
}
PROBLEM
let x = (0..<10).splitEvery( 3 )
XCTAssertEqual( x, [(0...2),(3...5),(6...8),(9)], "implementation broken" )
COMMENTS
I am running into problems calculating number of elements in the Range, etc...
extension Range
{
func splitEvery( nInEach: Int ) -> [Range]
{
let n = self.endIndex - self.startIndex // ERROR - cannot invoke '-' with an argument list of type (T,T)
}
}
The values in a range are of ForwardIndexType, so you can only advance() them,
or compute the distance(), but the subtraction - is not defined. The advance amount has to be of the corresponding
type T.Distance. So this would be a possible implementation:
extension Range {
func splitEvery(nInEach: T.Distance) -> [Range] {
var result = [Range]() // Start with empty array
var from = self.startIndex
while from != self.endIndex {
// Advance position, but not beyond the end index:
let to = advance(from, nInEach, self.endIndex)
result.append(from ..< to)
// Continue with next interval:
from = to
}
return result
}
}
Example:
println( (0 ..< 10).splitEvery(3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]
Note however that 0 ..< 10 is not a list (or array) of integers. To split an array into subarrays you could define a similar extension:
extension Array {
func splitEvery(nInEach: Int) -> [[T]] {
var result = [[T]]()
for from in stride(from: 0, to: self.count, by: nInEach) {
let to = advance(from, nInEach, self.count)
result.append(Array(self[from ..< to]))
}
return result
}
}
Example:
println( [1, 1, 2, 3, 5, 8, 13].splitEvery(3) )
// Output: [[1, 1, 2], [3, 5, 8], [13]]
A more general approach could be to split all sliceable objects. But Sliceable
is protocol and protocols cannot be extended. What you can do instead is to
define a function that takes the sliceable object as the first argument:
func splitEvery<S : Sliceable>(seq : S, nInEach : S.Index.Distance) -> [S.SubSlice] {
var result : [S.SubSlice] = []
var from = seq.startIndex
while from != seq.endIndex {
let to = advance(from, nInEach, seq.endIndex)
result.append(seq[from ..< to])
from = to
}
return result
}
(Note that this function is completely unrelated to the (extension) methods
defined above.)
Example:
println( splitEvery("abcdefg", 2) )
// Output: [ab, cd, ef, g]
println( splitEvery([3.1, 4.1, 5.9, 2.6, 5.3], 2) )
// Output: [[3.1, 4.1], [5.9, 2.6], [5.3]]
Ranges are not sliceable, but you could define a separate function that takes a
range argument:
func splitEvery<T>(range : Range<T>, nInEach : T.Distance) -> [Range<T>] {
var result : [Range<T>] = []
var from = range.startIndex
while from != range.endIndex {
let to = advance(from, nInEach, range.endIndex)
result.append(from ..< to)
from = to
}
return result
}
Example:
println( splitEvery(0 ..< 10, 3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]
I have this example of a fork/join calculation. Could somebody please describe me shortly how it works here?
def quicksortForkJoin(numbers) {
withPool {
runForkJoin(0, numbers) {index, list ->
def groups = list.groupBy {it <=> list[list.size().intdiv(2)]}
if ((list.size() < 2) || (groups.size() == 1)) {
return [index: index, list: list.clone()]
}
(-1..1).each { forkOffChild(it, groups[it] ?: [])}
return [index: index, list: childrenResults.sort {it.index}.sum {it.list}]
}.list
}
}
Any good?
def quicksortForkJoin(numbers) {
// Create a pool of workers the default size
withPool {
// Run a fork with index 0 and the numbers
runForkJoin(0, numbers) {index, list -> // [1]
// Split numbers into 3 groups:
// -1: those less than the "middle" number
// 0: those equal to the "middle" number
// 1: those greater than the "middle" number
def groups = list.groupBy {it <=> list[list.size().intdiv(2)]}
// If there are less than 2 numbers to sort, or all numbers are equal
if ((list.size() < 2) || (groups.size() == 1)) {
// return the index and a clone of the current list
return [index: index, list: list.clone()]
}
// Otherwise, fork off a child process for each of the
// groups above (less than, equal and greater than)
// forkOffChild will not block, and will effectively go back
// to line [1] with the new index and list
(-1..1).each { forkOffChild(it, groups[it] ?: [])}
// Block waiting for all 3 children to finish, then sort the
// results so the indexes are [ -1, 0, 1 ] and then join the
// lists of numbers back together
return [ index: index,
list: childrenResults.sort {it.index}.sum {it.list}]
// when done, return the `list` property from the final map
}.list
}
}
I have a collection of objects that I want to break up into a collection of collections, where each sequential group of 3 elements is in one collection.
For example, if I have
def l = [1,4,2,4,5,9]
I want to turn this into:
def r = [[1,4,2], [4,5,9]]
I'm doing it now by iterating over the collection and breaking it up.. but I then need to pass those 'groups' into a parallelized function that processes them.. It would be nice to eliminate this O(n) pre-processing work and just say something like
l.slice(3).collectParallel { subC -> process(subC) }
I've found the step method on the Range class, but it looks like that only acts on the indices. Any clever ideas?
Update:
I don't think this is a duplicate of the referenced link, although it's very close. As suggested below, it's more of the iterator-type thing I'm looking for.. the sub-collections will then be passed into a GPars collectParallel. Ideally I wouldn't need to allocate an entire new collection.
Check out groovy 1.8.6. There is a new collate method on List.
def list = [1, 2, 3, 4]
assert list.collate(4) == [[1, 2, 3, 4]] // gets you everything
assert list.collate(2) == [[1, 2], [3, 4]] //splits evenly
assert list.collate(3) == [[1, 2, 3], [4]] // won't split evenly, remainder in last list.
Take a look at the Groovy List documentation for more info because there are a couple of other params that give you some other options, including dropping the remainder.
As far as your parallel processing goes, you can cruise through the lists with gpars.
def list = [1, 2, 3, 4, 5]
GParsPool.withPool {
list.collate(2).eachParallel {
println it
}
}
If I understand you correctly, you're currently copying the elements from the original collection into the sub-collections. For more suggestions along those lines, checkout the answers to the following question: Split collection into sub collections in Groovy
It sounds like what you're instead looking for is a way for the sub-collections to effectively be a view into the original collection. If that's the case, check out the List.subList() method. You could either loop over the indices from 0 to size() in increments of 3 (or whatever slice size you choose) or you could get fancier and build an Iterable/List which would hide the details from the caller. Here's an implementation of the latter, inspired by Ted's answer.
class Slicer implements Iterator {
private List backingList
private int sliceSize
private int index
Slicer(List backingList, int sliceSize) {
this.backingList = backingList
this.sliceSize = sliceSize
}
Object next() {
if (!hasNext()) {
throw new NoSuchElementException()
}
def ret
if (index + sliceSize <= backingList.size()) {
ret = backingList.subList(index, index+sliceSize)
} else if (hasNext()) {
ret = backingList.subList(index, backingList.size())
}
index += sliceSize
return ret
}
boolean hasNext() {
return index < backingList.size()
}
void remove() {
throw new UnsupportedOperationException() //I'm lazy ;)
}
}
I like both solutions but here is a slightly improved version of the first solution that I like very much:
class Slicer implements Iterator {
private List backingList
private int sliceSize
private int index
Slicer(List backingList, int sliceSize) {
this.backingList = backingList;
int ss = sliceSize;
// negitive sliceSize = -N means, split the list into N equal (or near equal) pieces
if( sliceSize < 0) {
ss = -sliceSize;
ss = (int)((backingList.size()+ss-1)/ss);
}
this.sliceSize = ss
}
Object next() {
if (!hasNext()) {
throw new NoSuchElementException()
}
def ret = backingList.subList(index, Math.min(index+sliceSize , backingList.size()) );
index += sliceSize
return ret
}
boolean hasNext() {
return index < backingList.size() - 1
}
void remove() {
throw new UnsupportedOperationException() //I'm lazy ;)
}
List asList() {
this.collect { new ArrayList(it) }
}
List flatten() {
backingList.asImmutable()
}
}
// ======== TESTS
def a = [1,2,3,4,5,6,7,8];
assert [1,2,3,4,5,6,7,8] == a;
assert [[1, 2], [3, 4], [5, 6], [7, 8]] == new Slicer(a,2).asList();
assert [[1,2,3], [4,5,6], [7,8]] == (new Slicer(a,3)).collect { it } // alternative to asList but inner items are subList
assert [3, 2, 1, 6, 5, 4, 8, 7] == ((new Slicer(a,3)).collect { it.reverse() } ).flatten()
// show flatten iterator
//new Slicer(a,2).flattenEach { print it }
//println ""
// negetive slice into N pieces, in this example we split it into 2 pieces
assert [[1, 2, 3, 4], [5, 6, 7, 8]] == new Slicer(a,-2).collect { it as List } // same asList
assert [[1, 2, 3], [4, 5, 6], [7, 8]] == new Slicer(a,-3).asList()
//assert a == (new Slicer(a,3)).flattenCollect { it }
assert [9..10, 19..20, 29..30] == ( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) } )
assert [[9, 10], [19, 20], [29, 30]] == ( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) }.collect { it.flatten() } )
println( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) } )
println( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) }.collect { it.flatten() } )
There isn't anything built in to do exactly what you want, but if we #Delegate calls to the native lists's iterator, we can write our own class that works just like an Iterator that returns the chunks you're looking for:
class Slicer {
protected Integer sliceSize
#Delegate Iterator iterator
Slicer(objectWithIterator, Integer sliceSize) {
this.iterator = objectWithIterator.iterator()
this.sliceSize = sliceSize
}
Object next() {
List currentSlice = []
while(hasNext() && currentSlice.size() < sliceSize) {
currentSlice << this.iterator.next()
}
return currentSlice
}
}
assert [[1,4,2], [4,5,9]] == new Slicer([1,4,2,4,5,9], 3).collect { it }
Because it has all of the methods that a normal Iterator does, you get the groovy syntactic sugar methods for free with lazy evaluation on anything that has an iterator() method, like a range:
assert [5,6] == new Slicer(1..100, 2).find { slice -> slice.first() == 5 }
assert [[9, 10], [19, 20], [29, 30]] == new Slicer(1..30, 2).findAll { slice -> !(slice[1] % 10) }