Currently, I am working with ILGPU library. As I mentioned in the title briefly, I would like to go through the cameraSpacePoints and check whether the value is valid (if not infinity), if valid store the point in the Arrayview, as the code below.
However the kinect APIs (for e.g. new CameraSpacePoint[depthWidth * depthHeight] )can not be used in a kernel. So how can the below code actually work on GPU?
static void gpu_kernel(Index index,int depthWidth,int depthHeight, ArrayView<CameraSpacePoint> dataView)
{
CameraSpacePoint[] cameraSpacePoints
cameraSpacePoints = new CameraSpacePoint[depthWidth * depthHeight];
for (int i = 0; i < depthWidth*depthHeight; i++)
{
if (!(XMath.IsInfinity(cameraSpacePoints[i].X)))
{
dataView[i] = cameraSpacePoints[i];
}
}
}
Related
I am currently making a WPF App as a school project. I chose a Media player topic.
I have a slight problem with returning track length of a song and assigning it as a maximum for a slider (I used a slider for song seeking).
/*List<string> pathPesme = new List<string>();
path = od.FileNames;
for (int i = 0; i < path.Length; i++)
{
lista.Add(path[i]);
m.CreateControl();
media = this.m.newMedia(path[i]);*/
//When i want to instance a new class Pesma(song) and put the track length(duzina), it works and returns the value in a mm:ss format.
string ime = System.IO.Path.GetFileName(path[i]);
string duzina = media.durationString;
Pesma pesma = new Pesma(ime, path[i], duzina);
listaPesmi.Add(pesma);
}
However, when i try to do a similar thing and put it as Slider.Maximum, it doesn't work.
foreach (var pesma in dispesma)/**/
{
string aa=iseciString(lbxListaPesama.Items[lbxListaPesama.SelectedIndex].ToString(), ':');
//Method for cutting string to get song name
if (pesma.ImePesme == aa)
{
m.URL = pesma.Path;
premotajSlider.Maximum = Math.Ceiling(m.currentMedia.duration); //Slider: Here i try to put the max value. In the debugger, it returns a 0
m.Ctlcontrols.play();
jacinaZvukaSlider.Value = m.settings.volume;
}
}
It's my first time asking on StackOverflow, so I hope I didn't do something bad. If I did, sorry, still in the learning phase.
So, I want to store the inventory of the player in Firebase Realtime Database.
I set up a basic schema, and I want to add the items (their names, actually) under the inventory "branch".
I am trying to do it with the push method, but it ain't working for me right now.
I got the following script which updates the player's inventory client-side and should update the database to, with appending the inventory "branch".
What am I doing wrong?
public void pickUp() {
Transform free_place = findFirstFreePlace();
if(free_place) {
for (int i = 0; i < items.Length; i++) {
if (free_place.name.Contains(i.ToString())) {
items[i] = currentPickable;
reference.Child("users").Child(auth.CurrentUser.UserId).Child("inventory").Child(items[i].item_name).Push();
lastIndex = i;
}
}
free_place.GetChild(0).GetChild(0).GetComponent<Image>().sprite = items[lastIndex].item_pic;
free_place.GetChild(0).GetChild(0).GetComponent<Image>().enabled = true;
free_place.GetChild(1).GetComponent<Image>().enabled = true;
free_place.GetChild(1).GetComponent<Button>().interactable = true;
}
}
I'm guessing that there's slight confusion around what Push() does in this context. If you read the documentation, it says:
Add to a list of data. Every time you call Push(), Firebase generates a unique key that can also be used as a unique identifier, such as user-scores/<user-id>/<unique-score-id>.
Basically, it's giving you a place you can safely write into rather than actually adding something to the Database. You should check out the sample, but I think I can illustrate both what you intend to do and a cool way to use Push() for your use case.
public async void pickUp() {
Transform free_place = findFirstFreePlace();
if(free_place) {
int lastIndex = 0;
var elements = new List<string>();
for (int i = 0; i < items.Length; i++) {
if (free_place.name.Contains(i.ToString())) {
items[i] = currentPickable;
elements.Add(items[i].item_name);
lastIndex = i;
}
}
await reference.Child("users").Child(auth.CurrentUser.UserId).Child("inventory").SetValueAsync(itemNames);
free_place.GetChild(0).GetChild(0).GetComponent<Image>().sprite = items[lastIndex].item_pic;
free_place.GetChild(0).GetChild(0).GetComponent<Image>().enabled = true;
free_place.GetChild(1).GetComponent<Image>().enabled = true;
free_place.GetChild(1).GetComponent<Button>().interactable = true;
}
}
What I'm doing here is that I build a list of the items before hand. Then I set the inventory entry to this list. If I depended on the previous state, I'd probably prefer to do this as a transaction instead.
I also use async/await. I'm not sure how important it is that this logic runs before you update your game's UI, but setting anything in Firebase is an asynchronous operation (it runs in the background). You can omit this if it's not important that you stay in sync.
If you wanted to have uniquely identified weapon slots. You could instead do something like:
var childReference = reference.Child("users").Child(auth.CurrentUser.UserId).Child("inventory");
var key = childReference.Key;
// ... more logic here ...
childReference.Child(key).SetValueAsync(item_name);
A few more hints:
I'd recommend that you use the ValueChanged listener whenever possible to keep your game state in sync with your server state. Realtime Database will always be running asynchronously in the background, and this way you can help stay up to date as more data becomes available.
If asynchronous programming in Unity is new to you, check out my post on the subject.
Okay, so I've finally figured it out.
With the help of Push() method's unique id generation, I am able to add childs with the same item name to the inventory node.
Firstly, I create that unique id, then, I add that unique id to the database and set it's value to the item name.
Edit: I mixed my original solution with Pux0r3's solution, so that it uses async/await.
public async void pickUp() {
Transform free_place = findFirstFreePlace();
if (free_place) {
int lastIndex = 0;
var elements = new List<string>();
for (int i = 0; i < items.Length; i++) {
if (free_place.name.Contains(i.ToString())) {
items[i] = currentPickable;
elements.Add(items[i].item_name);
lastIndex = i;
}
}
string key = reference.Child(auth.CurrentUser.UserId).Child("inventory").Push().Key;
await reference.Child("users").Child(auth.CurrentUser.UserId).Child("inventory").Child(key).SetValueAsync(currentPickable.item_name);
free_place.GetChild(0).GetChild(0).GetComponent<Image>().sprite = items[lastIndex].item_pic;
free_place.GetChild(0).GetChild(0).GetComponent<Image>().enabled = true;
free_place.GetChild(1).GetComponent<Image>().enabled = true;
free_place.GetChild(1).GetComponent<Button>().interactable = true;
}
}
I have done some research and found solutions that apply to a void method, however I have been unable to replicate my code to that of a void as there is no overload for my method 'MD5' that matches the delegate 'ThreadStart', and I have been unable to convert a void to string, this programs intent is to show how multi-threading can allow for more than one process can be done at once. I intend to add additional processes on different threads, however, it is important that this works.
using System.Security.Cryptography;//Added to allow for UTF8 encoding
using System.Threading;//Added to allow for multi-threading
namespace MTSTask5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
//MD5 Hash method
public void MD5(string input)
{
MD5 md5 = new MD5CryptoServiceProvider();
//Convert the input string to a byte array and computer the hash, return the hexadecimal
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
string result = BitConverter.ToString(bytes).Replace("-", string.Empty);
return result.ToLower();
}
private void btnStartHash_Click(object sender, EventArgs e)
{
int loopQty = Int32.Parse(txtboxLoopQty.Text);
int i = 0;
//Create a while loop for the MD5 method below
while (i < loopQty)
{
//loop output
string HashOutput = MD5(MD5(txtboxHashOne.Text + txtboxHashTwo.Text));
txtboxHashOutput.Text = HashOutput + " " + i;
Thread HashThread = new Thread(new ThreadStart(MD5));
HashThread.Start();
i++;
}
}
Some suggestions that may help you troubleshoot and solve your problem:
First, I believe you may be trying to return result.ToLower(), a data type of string from your method named MD5, I'm guessing you were trying to use this instead of returning void, (i.e. nothing):
//MD5 Hash method
public string MD5(string input)
{
MD5 md5 = new MD5CryptoServiceProvider();
//Convert the input string to a byte array and computer the hash, return the hexadecimal
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
string result = BitConverter.ToString(bytes).Replace("-", string.Empty);
return result.ToLower();
}
That may not the entire problem, so let's check to make sure your method is working by copying the code you have in your btnStartHash_Click method into a safe place, and then replacing it with a simple message to yourself.
private void btnStartHash_Click(object sender, EventArgs e)
{
//Convert the input string to a byte array and computer the hash, return the hexadecimal and display it in a message box
MessageBox.Show(MD5("abcdefg"));//parse whatever known value test
}
If you are still unsure of the hash result from your MD5 method, then start taking parts out one by one.
Build the button click up again once you're certain of desired MD5 method's output:
private void btnStartHash_Click_(object sender, EventArgs e)
{
txtboxHashOne.Text = MD5(txtboxHashInput.Text);
string hashOfHash = MD5(txtboxHashOne.Text);
txtboxHashTwo.Text = hashOfHash;
}
In the above situation I'm using the MD5 method to hash the input textbox, txtboxHashInput.Text and then change the txtboxHashOne text box to reflect the change on the form. The txboxHashOne's entire string is then hashed to make sure to make the hashOfHash string.
Instead of having each instance txtboxHashOne , txtboxHashTwo, one may think it could do better by just creating the text box programmatically on the form:
//lets say the loopqty input is the number of times I wanted to hash this
int numberOfTimesToHash = Int32.Parse(txtboxLoopQty.Text);
//x and y represent where you want them to start appearing on your form..
int x = 10;
int y = 100;
int howeverManyThreadsIWant = numberOfTimesToHash;
for (int i = 0; i < howeverManyThreadsIWant; i++)
{
TextBox textBox = new TextBox();
textBox.Location = new Point(x, y);
//Could go into a recursive function such as` MD5(Input,recursionDepth)
//But instead going to reprint same hash for demonstration purposes
textBox.Text = MD5(txtboxHashInput.Text);
//MessageBox.Show(textBox.Text);
this.Controls.Add(textBox);
y += 30;
}
Then, the programmer may want to try to embrace a multithreaded approach to reduce complexity we have to do a lot more.
For example, unfortunately it's not so simple to do this:
//##!!Don't do this!!
var thread = new Thread(() =>
{
int x = 10;
int y = 100;
int howeverManyThreadsIWant = numberOfTimesToHash;
for (int i = 0; i < howeverManyThreadsIWant; i++)
{
TextBox textBox = new TextBox();
textBox.Tag = i;
textBox.Location = new Point(x, y);
//Could go into a recursive function such as MD5(Input,recursionDepth)
//But instead going to simply reprint same hash
textBox.Text = MD5(txtboxHashInput.Text);
//MessageBox.Show(textBox.Text);
this.Controls.Add(textBox);//<--invalid operations error
y += 30;
}
});
thread.Start();
would result in:
System.InvalidOperationException: 'Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.'<<
Strongly consider if you really need multithreading to solve this task.
Microsoft suggests:
When to Use Multiple Threads
Multithreading can be used in many common situations to significantly improve the responsiveness and usability of your application.
You should strongly consider using multiple threads to:
#Communicate over a network, for example to a Web server, database, or remote object.
#Perform time-consuming local operations that would cause the UI to freeze.
#Distinguish tasks of varying priority.
#Improve the performance of application startup and initialization.
It is useful to examine these uses in more detail.
Communicating Over a Network
#Smart-clients may communicate over a network in a number of ways, including:
#Remote object calls, such as DCOM, RPC or .NET remoting
#Message-based communications, such as Web service calls and HTTP requests
#Distributed transactions
With that in mind, if you really need to do these things, now that you have bug free code that is hashing the way you want it, visit the Using Multiple Threads by Microsoft.
Also you may want to check out Threading in Windows Forms, this has an example that you can run with most of what you need to know.
Hopefully some of this was what you were looking for.
I'm experimenting with OpenCL (through Cloo's C# interface). To do so, I'm experimenting with the customary matrix-multiplication-on-the-GPU. The problem is, during my speed tests, the application crashes. I'm trying to be efficient regarding the the re-allocation of various OpenCL objects, and I'm wondering if I'm botching something in doing so.
I'll put the code in this question, but for a bigger picture, you can get the code from github here: https://github.com/kwende/ClooMatrixMultiply
My main program does this:
Stopwatch gpuSw = new Stopwatch();
gpuSw.Start();
for (int c = 0; c < NumberOfIterations; c++)
{
float[] result = gpu.MultiplyMatrices(matrix1, matrix2, MatrixHeight, MatrixHeight, MatrixWidth);
}
gpuSw.Stop();
So I'm basically doing the call NumberOfIterations times, and timing the average execution time.
Within the MultiplyMatrices call, the first time through, I call Initialize to setup all the objects I'm going to reuse:
private void Initialize()
{
// get the intel integrated GPU
_integratedIntelGPUPlatform = ComputePlatform.Platforms.Where(n => n.Name.Contains("Intel")).First();
// create the compute context.
_context = new ComputeContext(
ComputeDeviceTypes.Gpu, // use the gpu
new ComputeContextPropertyList(_integratedIntelGPUPlatform), // use the intel openCL platform
null,
IntPtr.Zero);
// the command queue is the, well, queue of commands sent to the "device" (GPU)
_commandQueue = new ComputeCommandQueue(
_context, // the compute context
_context.Devices[0], // first device matching the context specifications
ComputeCommandQueueFlags.None); // no special flags
string kernelSource = null;
using (StreamReader sr = new StreamReader("kernel.cl"))
{
kernelSource = sr.ReadToEnd();
}
// create the "program"
_program = new ComputeProgram(_context, new string[] { kernelSource });
// compile.
_program.Build(null, null, null, IntPtr.Zero);
_kernel = _program.CreateKernel("ComputeMatrix");
}
I then enter the main body of my function (the part that will be executed NumberOfIterations times).
ComputeBuffer<float> matrix1Buffer = new ComputeBuffer<float>(_context,
ComputeMemoryFlags.ReadOnly| ComputeMemoryFlags.CopyHostPointer,
matrix1);
_kernel.SetMemoryArgument(0, matrix1Buffer);
ComputeBuffer<float> matrix2Buffer = new ComputeBuffer<float>(_context,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer,
matrix2);
_kernel.SetMemoryArgument(1, matrix2Buffer);
float[] ret = new float[matrix1Height * matrix2Width];
ComputeBuffer<float> retBuffer = new ComputeBuffer<float>(_context,
ComputeMemoryFlags.WriteOnly | ComputeMemoryFlags.CopyHostPointer,
ret);
_kernel.SetMemoryArgument(2, retBuffer);
_kernel.SetValueArgument<int>(3, matrix1WidthMatrix2Height);
_kernel.SetValueArgument<int>(4, matrix2Width);
_commandQueue.Execute(_kernel,
new long[] { 0 },
new long[] { matrix2Width ,matrix1Height },
null, null);
unsafe
{
fixed (float* retPtr = ret)
{
_commandQueue.Read(retBuffer,
false, 0,
ret.Length,
new IntPtr(retPtr),
null);
_commandQueue.Finish();
}
}
The third or fourth time through (it's somewhat random, which hints at memory access issues), the program crashes. Here is my kernel (I'm sure there are faster implementations, but right now my goal is just to get something working without blowing up):
kernel void ComputeMatrix(
global read_only float* matrix1,
global read_only float* matrix2,
global write_only float* output,
int matrix1WidthMatrix2Height,
int matrix2Width)
{
int x = get_global_id(0);
int y = get_global_id(1);
int i = y * matrix2Width + x;
float value = 0.0f;
// row y of matrix1 * column x of matrix2
for (int c = 0; c < matrix1WidthMatrix2Height; c++)
{
int m1Index = y * matrix1WidthMatrix2Height + c;
int m2Index = c * matrix2Width + x;
value += matrix1[m1Index] * matrix2[m2Index];
}
output[i] = value;
}
Ultimately the goal here is to better understand the zero-copy features of OpenCL (since I'm using Intel's integrated GPU). I have been having trouble getting it to work and so wanted to step back a bit to see if I understood even more basic things...apparently I don't as I can't get even this to work without blowing up.
The only other thing I can think of is it's how I'm pinning the pointer to send it to the .Read() function. But I don't know of an alternative.
Edit:
For what it's worth, I updated the last part of code (the read code) to this, and it still crashes:
_commandQueue.ReadFromBuffer(retBuffer, ref ret, false, null);
_commandQueue.Finish();
Edit #2
Solution found by huseyin tugrul buyukisik (see comment below).
Upon placing
matrix1Buffer.Dispose();
matrix2Buffer.Dispose();
retBuffer.Dispose();
At the end, it all worked fine.
OpenCl resources like buffers, kernels and commandqueues should be released after other resources that they are bound-to are released. Re-creating without releasing depletes avaliable slots quickly.
You have been re-creating arrays in a method of gpu and that was the scope of opencl buffers. When it finishes, GC cannot track opencl's unmanaged memory areas and that causes leaks, which makes crashes.
Many opencl implementations use C++ bindings which needs explicit release commands by C#, Java and other environments.
Also the set-argument part is not needed many times when repeated kernel executions use exact same buffer order as parameters of kernel.
I am trying to optimize my engine (C# + SlimDX) to make as less allocations as possible (to prevent the GC from firing too often) using as guide a profiler that gives me where the garbaged object are generated. Its going pretty well (going down from like 20 MB garbaged every 5s to 8 MB garbaged every 1 minute and half (yep, it was very little optimized XD))
There is a method where I can't find anything declarated and i don't know what's to do. It seems this method generate 2 garbaged object per execution in its body (not on a called function) :
Can somebody guide me to understand why this function generate object to be garbaged? I really don't have a clue.
public override void Update()
{
base.Update();
if (LastCheckInstancesNumber != Instances.Count)
{
LastCheckInstancesNumber = Instances.Count;
_needToRegenerateUpdate = true;
}
// Crea byte array da usare nel prossimo draw.
if (_needToRegenerateUpdate)
{
Int32 PrimitivesCount = Instances.Count;
Int32 Size = PrimitivesCount * 80;
if ((ByteUpdateTemp != null) && (ByteUpdateTemp.Length < Size))
ByteUpdateTemp = new byte[Size];
int offset = 0;
PrimitivesCount = 0;
Int32 Count = Instances.Count;
for (int i = 0; i < Count; i++)
{
InstancedBase3DObjectInstanceValues ib = Instances[i];
if (ib.Process)
{
MathHelper.CopyMatrix(ref ib._matrix, ref MatrixTemp);
MathHelper.CopyVector(ref ib._diffuseColor, ref ColorTemp);
ObjectUpdateTemp[0] = MatrixTemp.M11;
ObjectUpdateTemp[1] = MatrixTemp.M12;
ObjectUpdateTemp[2] = MatrixTemp.M13;
ObjectUpdateTemp[3] = MatrixTemp.M14;
ObjectUpdateTemp[4] = MatrixTemp.M21;
ObjectUpdateTemp[5] = MatrixTemp.M22;
ObjectUpdateTemp[6] = MatrixTemp.M23;
ObjectUpdateTemp[7] = MatrixTemp.M24;
ObjectUpdateTemp[8] = MatrixTemp.M31;
ObjectUpdateTemp[9] = MatrixTemp.M32;
ObjectUpdateTemp[10] = MatrixTemp.M33;
ObjectUpdateTemp[11] = MatrixTemp.M34;
ObjectUpdateTemp[12] = MatrixTemp.M41;
ObjectUpdateTemp[13] = MatrixTemp.M42;
ObjectUpdateTemp[14] = MatrixTemp.M43;
ObjectUpdateTemp[15] = MatrixTemp.M44;
ObjectUpdateTemp[16] = ColorTemp.X;
ObjectUpdateTemp[17] = ColorTemp.Y;
ObjectUpdateTemp[18] = ColorTemp.Z;
ObjectUpdateTemp[19] = ColorTemp.W;
ByteConverter.WriteSingleArrayToByte(ref ObjectUpdateTemp, ref ByteUpdateTemp, offset);
offset += 20;
PrimitivesCount++;
}
}
SynchronizedObject so = SynchronizationEventWriter.LockData();
so.Synchronizedobject = ByteUpdateTemp;
SynchronizationEventWriter.Update();
SynchronizationEventWriter.UnlockData();
_needToRegenerateUpdate = false;
so = SynchronizationEventWriterNum.LockData();
so.Synchronizedobject = PrimitivesCount;
SynchronizationEventWriterNum.Update();
SynchronizationEventWriterNum.UnlockData();
}
}
Notes :
The new byte[Size] is NEVER called due to caching.
The MathHelper function simply copy each element (Single) from one object to another without creating anything.
The base.Update() does almost nothing (and anyway is derived from ALL object in my engine, but only here i have the garbage object)
Thanks!!!
EDIT:
internal void GetLock()
{
Monitor.Enter(InternalLock);
Value.Locked = true;
Value.LockOwner = Thread.CurrentThread;
}
public SynchronizedObject LockData()
{
Parent.GetLock();
return Parent.Value;
}
Here's the code of the LockData(). I don't think it generates anything :|
I've resolved!!!
The problem was that the so.Synchronizedobject = PrimitivesCount; was assigning an Int32 to an Object class. It seems that this replaces every time the object causing the old object to be garbaged.
I resolved by using a box class to enclose the Int32 object and simply change the value inside.
What's in base.Update(), anything?
Can your profiler dump the heap? If so why I'd put a breakpoint just before this method and dump the heap and then again straight afterwards. That way you'll be able to see what type of object has been created.
Short of that a brute force approach of commenting out line by line is another (horrible) idea.
Do your MathHelper methods create a temp object?
I'm just guessing, but it looks like you're creating two SynchronizedObject objects in the bottom nine lines of that function:
SynchronizedObject so = SynchronizationEventWriter.LockData();
and
so = SynchronizationEventWriterNum.LockData();
No detailed knowledge of SynchronizedObject or whether LockData() actually creates anything, but it's the only choice I can see in your code...