I am using kotlin in combination with lwjgl. So far I had the following code that ran several thousand times per second:
// val textureMap = HashMap<Int, Texture>()
fun bind() {
var index = 0
for(entry in textureMap) {
glActiveTexture(GL_TEXTURE0 + index)
entry.value.bind()
program.setInt(entry.key, index)
++index
}
}
So while this was running absolutely fast and consumed virtually 0 of my frame time as expected I had to replace it because it created an Iterator in every call, eventually leading to tens of thousands of those objects eventually getting garbage collected and halting my program for a few milliseconds which is of course not usable in my application.
So I went ahead and changed it to the following code:
// textures = ArrayList<Texture>()
// indices = ArrayList<Int>()
fun bind() {
var index = 0
while(index < textures.size) {
val uniform = indices[index]
val texture = textures[index]
glActiveTexture(GL_TEXTURE0 + index)
texture.bind()
program.setInt(uniform, index)
++index
}
}
Now for some reason I am noticing a massive drop in performance, namely the function now uses several seconds per frame. Using jvisualvm I was able to determine that all that time is spent in glActiveTexture in the native part as well as the native function in program.setInt(...). I am absolutely stumped why this is the case, especially after comparing the byte code of the two.
This is the decompiled class file for the first (fast) version:
public final void bind()
{
int index = 0;
Map localMap = (Map)this.textureMap;
for (Map.Entry entry : localMap.entrySet())
{
GL13.glActiveTexture(33984 + index);
((Texture)entry.getValue()).bind(); Program
tmp66_63 = this.program;
if (tmp66_63 == null) {
Intrinsics.throwUninitializedPropertyAccessException("program");
}
tmp66_63.setInt(((Number)entry.getKey()).intValue(), index);
index++;
}
}
And that is the byte code of the slow version:
public final void bind()
{
int index = 0;
while (index < this.textures.size())
{
Integer uniform = (Integer)this.indices.get(index);
Texture texture = (Texture)this.textures.get(index);
GL13.glActiveTexture(33984 + index);
texture.bind(); Program
tmp52_49 = this.program;
if (tmp52_49 == null) {
Intrinsics.throwUninitializedPropertyAccessException("program");
}
Integer tmp62_61 = uniform;Intrinsics.checkExpressionValueIsNotNull(tmp62_61, "uniform");tmp52_49.setInt(tmp62_61.intValue(), index);
index++;
}
}
I am extremely confused what is going on here. In both versions the call to glActiveTexture is GL_TEXTURE0 + <an int value>, yet one takes so much more time thatn the other.
Does anyone have an idea what I am missing here?
Basically my entire question can be removed. I should have debugged and not only profiled. The problem was the code that populated the lists, and it didnt remove the old values so the lists grew larger and larger and the loop just ran so many more times over time...
In case anyone was wondering how I fixed my problem with the allocations I essentially created two collections, one is containing the uniforms and one is mapping them to textures. And then I can iterate over the uniforms and then get the respective texture. So no pointless Iterator objects are created but I am also not having any duplicates :)
Related
I'm an Italian student and I'm new in programming. I need your help for a school project.
I'm making a blob tracking program using Daniel Shiffman's tutorials. Currently I have 2 blobs on the screen. I am identifying them with 2 IDs: number 0 and number 1.
I need to put some conditions on those blobs: if one blob is in a certain part of the screen and the other one is in another part, I need to call a function.
I don't know how to put the if conditions separately for the two ids. Below is some pseudo code of what I would like to achieve:
for (id==0)
if (...) and
for (id==1)
if(...) then {
void()
}
I would really appreciate any help!
I don't really know where you want the blobs to be when the desired function fires, but I can try to give you an example...
Blob
Assign some sort of position variable, in this case PVector, to your blob object.
class Blob {
PVector position;
Blob (PVector position) {
this.position = position;
}
void update() {
*random movements, etc...*
}
}
Create two blob objects
Create two objects and assign a position to each of them.
Blob[] blobs = new Blob[2];
void setup() {
size(400, 400);
blobs[0] = new Blob(5, new PVector(40, 40));
blobs[1] = new Blob(13, new PVector(100, 100));
}
Check if blobs is at left or right side of the screen
I check if blob[0] is at the left side of the screen and if blob[1] is at right side of the screen. If they are, at the same time, the desiredFunction(); will fire.
void draw() {
for (int i = 0; i < blobs.length; i++) {
blobs.update();
}
if (blobs[0].position.x < (width / 2) && blobs[1].position.x < (width / 2) {
desiredFunction();
}
}
Remember
This is just an example. You could of course check other parts of the screen instead of the left and right parts. You can also use IDs on your blobs instead of an array, I just thought it was better to just use an array in this case.
PS: I wrote this answer without having processing started. The code has certainly a couple of typing errors.
For the example you have described, you can achieve this using the && operator in one if statement.
First assign the conditions you want to test to boolean variables. For example, create the boolean variables id0IsThere, and id1IsThere, and set them to true if the blobs are in the locations you want them to be in. Then use the following if statement:
if (id0IsThere && id1IsThere) {
yourFunction();
}
The && operator means that the code inside the if statement that executes yourFunction() is only executed if both conditions are true. In this case, if both blobs are in the positions you want them to be in. Hope that helps. Read more about if statements and the && operator here:
https://processing.org/reference/if.html
https://processing.org/reference/logicalAND.html
I'm trying to plot some graphs simultaneously:
Each representing an attribute and displays the results for several objects each containing its own data items series.
I encounter very bad performance using either add(...) or addOrUpdate(...) methods of the TimeSeries - time for plotting ~16,000 items is about 60 seconds.
I read about the performance issue - http://www.jfree.org/phpBB2/viewtopic.php?t=12130&start=0 - but it seems to me like it is much worse in my case for some reason.
I'd like to understand whether this is truly the performance that I may squeeze out of the module (2.5GHz machine running windows - I doubt that).
How can I get my application accelerated with this respect?
Here is a basic version of the code (note that it is all done in a dedicated thread):
/* attribute -> (Object -> graph values) */
protected HashMap<String,HashMap<Object,Vector<TimeSeriesDataItem>>> m_data =
new HashMap<String,HashMap<Object,Vector<TimeSeriesDataItem>>>();
public void loadGraph() {
int items = 0;
for (String attr : m_data.keySet())
for (Object obj : m_data.get(attr).keySet())
for (TimeSeriesDataItem dataItem : m_data.get(attr).get(obj))
items++;
long before = System.currentTimeMillis();
// plot each graph
for (String attr : m_data.keySet()) {
GraphXYPlot plot = m_plots.get(attr);
plot.addToObservation(m_data.get(attr));
}
System.err.printf("Time for plotting %d items is: %d ms", items, System.currentTimeMillis()-before);
// => Time for plotting 16540 items is: 59910 ms
}
public void addToObservation(HashMap<Object, Vector<TimeSeriesDataItem>> plotData) {
for (Object obj : plotData.keySet()) {
SeriesHandler handler = m_series.get(obj);
if (handler != null) {
TimeSeries fullSeries = handler.getFullSeries();
TimeSeries periodSeries = handler.getPeriodseries();
for (TimeSeriesDataItem dataItem : plotData.get(obj)) {
fullSeries.add(dataItem);
periodSeries.add(dataItem);
}
}
}
}
Thanks a lot !
Guy
Absent more details, any of several general optimizations should be considered:
Invoke setNotify(false), as suggested here.
Cache already calculated values, as discussed here.
Adopt a paging strategy, as shown here.
Chart a summary of average/time-unit values; based on the ChartEntity seen in a ChartMouseListener, show an expanded subset in an adjacent panel.
I am trying to learn LINQ but it is quite confusing at first!
I have a collection of items that have a color property (MyColor). I have another collection of all colors (called AvailableColors - lets say 10 for example).
I want to get a random color from the AvailableColors that does not already exist in my collection.
My current C# code just gets a random color but I would like to rewrite this in LINQ to take in the current color collection and exclude those from the possible options:
public MyColor GetRandomColour()
{
return AvailableColors[new Random().Next(0, AvailableColors.Count)];
}
so it would take in the existing collection:
public MyColor GetRandomColour(ListOfSomethingWithColorProperty)
Thanks for any pointers!
Excluding already-used colors implies saving of state. You might be better off writing an iterator and using yield return to return the next random color in the sequence. This allows you to "remember" which colors have already been used.
Once you have that, you can call it using Take(1) from Linq, if you wish.
// assumes Random object is available, preferrably a re-used instance
Color color = AvailableColors
.Except(myItems.Select(item => item.Color).Distinct())
.OrderBy(c => random.Next())
.FirstOrDefault();
Probably not terribly efficient, but also probably not a concern given a small number of items.
Another approach is to randomly order the available colors once beforehand, therefore you can go in order. Use a List<Color> so you can remove elements as you use them, or save the current index with each pull. Once the list is depleted or the index exceeds the length of the array, notify your user that you're all out of colors.
var rnd = new Random(); // don't keep recreating a Random object.
public MyColor GetRandomColour(List<Something> coll)
{
var len = rnd.Next(0, AvailableColors.Count- coll.Count);
return AvailableColors.Except(coll.Select(s=>s.MyColor)).Skip(len).First();
}
I'm going to suggest that you be Linq-minded and create a good, general purpose IEnumerable<T> extension method that does the heavy lifting you require and then your GetRandomColor functions are simpler and you can use the extension method for other similar tasks.
So, first, define this extension method:
public static IEnumerable<T> SelectRandom<T>(this IEnumerable<T> #this, int take)
{
if (#this == null)
{
return null;
}
var count = #this.Count();
if (count == 0)
{
return Enumerable.Empty<T>();
}
var rnd = new Random();
return from _ in Enumerable.Range(0, take)
let index = rnd.Next(0, count)
select #this.ElementAt(index);
}
This function allows you to select zero or more randomly chosen elements from any IEnumerable<T>.
Now your GetRandomColor functions are as follows:
public static MyColor GetRandomColour()
{
return AvailableColors.SelectRandom(1).First();
}
public static MyColor GetRandomColour(IEnumerable<MyColor> except)
{
return AvailableColors.Except(except).SelectRandom(1).First();
}
The second function accepts an IEnumerable<MyColor> to exclude from your available colors so to call this function you need to select the MyColor property from your collection of items. Since you did not specify the type of this collection I felt it was better to use IEnumerable<MyColor> rather than to make up a type or to define an unnecessary interface.
So, the calling code looks like this now:
var myRandomColor = GetRandomColour(collectionOfItems.Select(o => o.MyColor));
Alternatively, you could just directly rely on Linq and the newly created extension method and do this:
var myRandomColor =
AvailableColors
.Except(collectionOfItems.Select(o => o.MyColor))
.SelectRandom(1)
.First();
This alternative is more readable and understandable and will aid maintainability of your code. Enjoy.
There's a nifty way to select a random element from a sequence. Here it's implemented as an extention method:
public static T Random<T>(this IEnumerable<T> enumerable)
{
var rng = new Random(Guid.NewGuid().GetHashCode());
int totalCount = 0;
T selected = default(T);
foreach (var data in enumerable)
{
int r = rng.Next(totalCount + 1);
if (r >= totalCount)
selected = data;
totalCount++;
}
return selected;
}
This method uses the fact that probability to choose n-th element over m-th when iterating is 1/n.
With this method, you can select your colour in one line:
var color = AvailableColors.Except(UsedColors).Random();
I just started playing with the Task Parallel Library, and ran into interesting issues; I have a general idea of what is going on, but would like to hear comments from people more competent than me to help understand what is happening. My apologies for the somewhat lengthy code.
I started with a non-parallel simulation of a random walk:
var random = new Random();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var simulations = new List<int>();
for (var run = 0; run < 20; run++)
{
var position = 0;
for (var step = 0; step < 10000000; step++)
{
if (random.Next(0, 2) == 0)
{
position--;
}
else
{
position++;
}
}
Console.WriteLine(string.Format("Terminated run {0} at position {1}.", run, position));
simulations.Add(position);
}
Console.WriteLine(string.Format("Average position: {0} .", simulations.Average()));
stopwatch.Stop();
Console.WriteLine(string.Format("Time elapsed: {0}", stopwatch.ElapsedMilliseconds));
Console.ReadLine();
I then wrote my first attempt at a parallel loop:
var localRandom = new Random();
stopwatch.Reset();
stopwatch.Start();
var parallelSimulations = new List<int>();
Parallel.For(0, 20, run =>
{
var position = 0;
for (var step = 0; step < 10000000; step++)
{
if (localRandom.Next(0, 2) == 0)
{
position--;
}
else
{
position++;
}
}
Console.WriteLine(string.Format("Terminated run {0} at position {1}.", run, position));
parallelSimulations.Add(position);
});
Console.WriteLine(string.Format("Average position: {0} .", parallelSimulations.Average()));
stopwatch.Stop();
Console.WriteLine(string.Format("Time elapsed: {0}", stopwatch.ElapsedMilliseconds));
Console.ReadLine();
When I ran it on a virtual machine set to use 1 core only, I observed a similar duration, but the runs are no longer processed in order - no surprise.
When I ran it on a dual-core machine, things went odd. I saw no improvement in time, and observed some very weird results for each run. Most runs end up with results of -1,000,000, (or very close), which indicates that Random.Next is returning 0 quasi all the time.
When I make the random local to each loop, everything works just fine, and I get the expected duration improvement:
Parallel.For(0, 20, run =>
{
var localRandom = new Random();
var position = 0;
My guess is that the problem has to do with the fact that the Random object is shared between the loops, and has some state. The lack of improvement in duration in the "failing parallel" version is I assume due to that fact that the calls to Random are not processed in parallel (even though I see that the parallel version uses both cores, whereas the original doesn't). The piece I really don't get is why the simulation results are what they are.
One separate worry I have is that if I use Random instances local to each loop, I may run into the problem of having multiple loops starting with the same seed (the issue you get when you generate multiple Randoms too close in time, resulting in identical sequences).
Any insight in what is going on would be very valuable to me!
Neither of these approaches will give you really good random numbers.
This blog post covers a lot of approaches for getting better random numbers with Random
Link
These may be fine for many day to day applications.
However if you use the same random number generator on multiple threads even with different seeds you will still impact the quality of your random numbers. This is because you are generating sequences of pseudo-random numbers which may overlap.
This video explains why in a bit more detail:
http://software.intel.com/en-us/videos/tim-mattson-use-and-abuse-of-random-numbers/
If you want really random numbers then you really need to use the crypto random number generator System.Security.Cryptography.RNGCryptoServiceProvider. This is threadsafe.
The Random class is not thread-safe; if you use it on multiple threads, it can get messed up.
You should make a separate Random instance on each thread, and make sure that they don't end up using the same seed. (eg, Environment.TickCount * Thread.CurrentThread.ManagedThreadId)
One core problem:
random.Next is not thread safe.
Two ramifications:
Quality of the randomness is destroyed by race conditions.
False sharing destroys scalability on multicores.
Several possible solutions:
Make random.Next thread safe: solves quality issue but not scalability.
Use multiple PRNGs: solves scalability issue but may degrade quality.
...
I have a flashlite3 application with navigation consisting of icons the user can browse left or right through infinitely.
The basic algorithm i'm using now works (and is adequate for this project) however, part of the solution depends on a duplicate of the array of icons. Depending on the number of items in the array, and/or the size of the element contents, this solution could become less efficient. I'm interested in a solution or algorithm(in any language) that could achieve the same thing while being scalable & efficient.
Heres a portion of relevant code in the setter function for mutating the '_selectedItem' property, which:
Evaluates the current '_selectedItem' and the new '_value'
Based on step 1 pop,unshifts right, or shift,pops left
Repeats step 2 until the icon matching the '_selectedItem' is in the center of the array
This code runs using 3 arrays:
[static] Array of positions. There are 5 icons, 3 are visible at a time, so position 0 is off stage, position 1 is 1/3, position 2 is 1/2 ..
When instantiating the icons 2 arrays are created: _viewArray & _icons. The order of _viewArray mimics the order to be displayed and _icons is left alone and used for the loop condition checking
///Actionscript2///
public function set selectedItem(value:Number)
{
var w=Stage.width;
if(value > _icons.length-1)
{
value=0;
}else if(value < 0)
{
value=_icons.length-1;
}
if(value > _selectedIndex)
{
while(_viewArray[Math.floor(_icons.length*.5)] != _icons[value])
{
var element;
element=_viewArray.pop();
_viewArray.unshift(element);
}
}else if(value < _selectedIndex)
{
while(_viewArray[Math.floor(_icons.length*.5)]!=_icons[value])
{
var element;
element=_viewArray.shift();
_viewArray.push(element);
}
}
for(var i:Number=0;i<_viewArray.length;i++)
{
if(i>=1 && i<= _icons.length-2)
{
_viewArray[i]._visible=true;
}else
{
_viewArray[i]._visible=false;
}
Tweener.addTween(_viewArray[i],{_x:positions[i],_alpha:80,time:.5,transition:'elasticIn'})
}
Tweener.addTween(_icons[(_viewArray.length*.5)-1],{_alpha:100,time:.0,transition:'elasticIn'});
Tweener.addTween(_selectedServiceIndicator,{_alpha:0,time:.3,transition:'elasticIn',onComplete:function() {Tweener.addTween(this,{_alpha:100,time:.2,transition:'elasticIn'});}});
var eventObject:Object = {target:this, type:'SelectedItemChange'};
eventObject.value=value;
for(var key in _serviceData[value])
eventObject[key]=_serviceData[value][key];
dispatchEvent(eventObject);
_selectedIndex=value;
}
Why does each element of the _viewArray has to actually store the icon, rather than only the index into the _icons array? This way you only have the icons stored once, and _viewArray just stores their presentation order.