I think you're trying to impress all of us with your supposed in-depth knowledge about processors' architecture. I'm still waiting to be impressed.
And I considered for a moment to actually try and clear any misconceptions expressed in your latest comment, and then realized that you're not actually interested. You're just a troll.
is telling the compiler "i'm going to use these two arrays in different cores, so be so kind to generate assembler code to handle this efficiently".
Nothing to do with assembler code, everything to do with data layout in memory, how the data is loaded into cache lines, and whether or not multiple hardware threads accessing the same cache line will be causing lots of cache invalidation or not.
So, it's a compiler problem, not an OOP problem. Two different levels of abstraction.
No, it's not a compiler problem. The C/C++ standards mandate certain things that make this unavoidable; structs must be contiguous bits in memory, and adjacent array elements must be adjacent in memory. The rest follows from there (and an understanding of cache architectures).
On the other hand, I have a problem with this statement in the context of the current discussion:
The bottleneck isn't CPU any longer, it's loading data from main memory into the CPU caches for the most part
Who cares? A worse bottleneck is reading from a RDBMS. The processor's cache is orders of magnitude apart if you think in terms of levels of abstraction.
Entirely dependent on your problem. If reading from RDBMS is your problem, then this discussion is of little or no worth to you. Just because you can't use information doesn't make it wrong, though. There are plenty of people in the world to whom this type of optimization matters.
The CS courses are presumably supposed to impart knowledge about what types of problems exist with parallelization. The same underlying problem, for example, also exists for distributing work to multiple CPUs, or to multiple machines. MapReduce, for example, is pretty much the same principle applied at a much higher level of abstraction - and probable about the level of abstraction that matters to you if you see RDBMS as the major bottlenecks in your experience.
Let's look at a single thing to do first and ignore parallel.
These days processors are incredibly fast at executing instructions on register values. The bottleneck isn't CPU any longer, it's loading data from main memory into the CPU caches for the most part. That's simplifying things a lot, but let's keep it at that.
With the example I've given, you've got two ints per struct, and a reasonably large number of these structs. The 200 I've given was just an example. You've also got a problem that involves only one of those ints, say, finding the highest in your set. Because you're loading both ints into the cache, but only need half of them, you'll be forced to perform twice as many loads than if you had two arrays of ints.
Now add a second problem; say, calculate the sum of the other ints. The crucial part is that one of these problems may take longer than the other to execute. That means, that at the point where one piece of code is done with the contents of a cache line, it'll try and replace it with the next chunk of data. The first problem, however, still needs the first chunk of data, so will cause this to load into cache the next time it executes. Instead of having "just" twice as many loads as you need, you might end up having hundreds.
This is not an unlikely scenario. The CPU caches will get filled with data from main memory as it's requested, i.e. when the first int is accessed for solving the first problem. When the CPU switches to processing the second problem, the data is already in cache and not loaded into a separate cache page. Unless the problems are solved at *exactly* the same speed, i.e. both problems will cause the next page of data at the same time, you *will* run into this issue.
Keep the two data sets in two separate arrays, and you'll use two cache lines. But they can be flushed and re-filled independently from each other, leading to fewer loads.
This sort of problem doesn't occur for every type of parallelization, mind you. If you try to parallelize by offloading two pieces of work to two different machines, it's not an issue. If you've got a single problem to solve that covers both ints, you don't have that problem - you can still paralellize, and parallelize pretty well, by running two hardware threads that each process half of the data set. And so on.
The point is that by getting too used to thinking in terms of arrays of structs instead of several separate arrays, you pretty much prevent yourself from solving certain parallelization problems efficiently. It's not that this *must* be bad, it's that it *can* be bad. But if you think in terms of arrays of structs, you're unlikely to even know.
I probably should've posted this straight away, but I would recommend two pieces of reading: - http://lwn.net/Articles/250967/ (all parts) gives a good idea of all the sorts of effects that memory layout can have on your program's performance, and what you can do about it (to the degree that you can). - http://www.slideshare.net/naughty_dog/multiprocessor-game-loops-lessons-from-uncharted-2-among-thieves specifically speaks about how to improve parallel processing efficiency by (amongst other things) doing what I wrote about above.
See, I don't even mind whether assembly or OOP in a high level language gets taught first. Either way, it helps to learn both to master all aspects of programming.
Personally, I'd prefer to start with assembly, but I've met plenty of people who were sufficiently confused by higher level programming languages that that wouldn't have been useful for them. And to be fair, plenty of programmers will never need to understand assembly, but still earn a decent living and contribute to the state of the art in other ways.
It really depends what you want to achieve. Get many people ready to earn a living? Might as well start with OOP. Get programmers to as high a level of understanding as possible? Probably start with assembly, then.
No, but reading helps. I did not say "this is OOP" anywhere.
One of the unintended consequences of OOP is that data tends to be laid out in memory in a similar fashion as I showed, which in turn is less than ideal for efficient parallelization of some tasks. That's all I said.
My point is that the struct you showed represents not a drawback of OOP, but an advantage that is lost in a procedural approach like that, which is the separation between the data layout and the code using the data structure, enabling changes to the data layout at any time without affecting existing code.
We're talking about parallelism here. You might have a point when talking about OOP in general, but when it comes to parallelizing code, this can be a huge drawback to efficiency. That's all I said, that's all I care about for the purposes of this conversation.
It's a problem that exists with certain approaches to creating parallel software, and has little to do with your programming language of choice in the first instance. Well, some languages don't let you control the layout of data in memory, for better or worse, so your choice does play a role... but it's mostly a question of paradigms than languages.
I gave an example in Haskell exactly because it follows different paradigm, being functional instead of OO.
Indeed. Nobody says that other paradigms might not have similar problems. But a purely procedural approach wouldn't necessarily.
The OOP paradigm is problematic for parallel programming because it suggests the inefficient approach; it doesn't require you to write inefficient code, nor does it prevent you from writing efficient code. It's very unlikely that an inexperienced programmer will chose an approach that is in conflict with the paradigm they were taught, though.
But I don't see how OOP suggests the inefficient approach any more than other paradigms.
It suggests that you think of your data in terms of conglomerates of related data items (structures) first, and consider collections (lists, arrays) of such conglomerates second. Many times, parallelization is best achieved by picking these apart into one or more collections of non-conglomerated data. OOP practically forces you to think in terms of conglomerated data, though.
No, but reading helps. I did not say "this is OOP" anywhere.
One of the unintended consequences of OOP is that data tends to be laid out in memory in a similar fashion as I showed, which in turn is less than ideal for efficient parallelization of some tasks. That's all I said.
Second, I don't see how that's not a problem in any other language. For example, in an Haskell tutorial on haskell.org, they show you the type:
type AssocList a b = [(a,b)]
Which is basically the same as the first struct.
It's a problem that exists with certain approaches to creating parallel software, and has little to do with your programming language of choice in the first instance. Well, some languages don't let you control the layout of data in memory, for better or worse, so your choice does play a role... but it's mostly a question of paradigms than languages.
The OOP paradigm is problematic for parallel programming because it suggests the inefficient approach; it doesn't require you to write inefficient code, nor does it prevent you from writing efficient code. It's very unlikely that an inexperienced programmer will chose an approach that is in conflict with the paradigm they were taught, though.
It's anti-parallel because it invites you to do this:
struct foo {
int a;
int b; }; foo asdf[200];
Instead of:
struct asdf {
int a[200];
int b[200]; };
The data layout in the first case does not exactly lend itself to efficiently processing all a in parallel to all b.
As with most programming paradigms, if you understand their limitations, you can work around them. But they do suggest certain ways of structuring code that may not be good for all applications.
Google translate suggests that this is not, in fact, a third explosion, but an explosion at the third reactor core. Which I've seen on the news a few hours ago. So it's the second explosion. Could anyone with better understanding of Japanese confirm?
Nothing wrong with de-facto standards, if they're fully open.
Look at e.g. the Python programming language. The CPython implementation is the de-facto standard implementation, and the language specs actually refer (or used to) to the implementation saying if in doubt, that implementation wins.
Yet there are other, mostly compatible Python implementations out there, and nothing - not patents, nor secrets - stops you from starting a new one.
The whitepaper examines the permissions apps request, not the actions apps perform.
Sadly requested permissions are not nearly as good an indicator for potential threats as one might think. In my own app, for example, I require the permission to read contact data - there is a use-case for that. However, that in no way implies that the app e.g. harvests email addresses for a spam service. Which it easily could, with that permission.
The discussion about whether or not is a word is what seems like a waste of effort to me.
But my previous comment wasn't meant to be a call for people to use the word "malamanteau", it was a call for people to use whatever words they like. That's what keeps language alive and kicking.
I think you're trying to impress all of us with your supposed in-depth knowledge about processors' architecture. I'm still waiting to be impressed.
And I considered for a moment to actually try and clear any misconceptions expressed in your latest comment, and then realized that you're not actually interested. You're just a troll.
Nothing, absolutely nothing in this:
struct asdf {
int a[200];
int b[200];
};
is telling the compiler "i'm going to use these two arrays in different cores, so be so kind to generate assembler code to handle this efficiently".
Nothing to do with assembler code, everything to do with data layout in memory, how the data is loaded into cache lines, and whether or not multiple hardware threads accessing the same cache line will be causing lots of cache invalidation or not.
So, it's a compiler problem, not an OOP problem. Two different levels of abstraction.
No, it's not a compiler problem. The C/C++ standards mandate certain things that make this unavoidable; structs must be contiguous bits in memory, and adjacent array elements must be adjacent in memory. The rest follows from there (and an understanding of cache architectures).
On the other hand, I have a problem with this statement in the context of the current discussion:
The bottleneck isn't CPU any longer, it's loading data from main memory into the CPU caches for the most part
Who cares? A worse bottleneck is reading from a RDBMS. The processor's cache is orders of magnitude apart if you think in terms of levels of abstraction.
Entirely dependent on your problem. If reading from RDBMS is your problem, then this discussion is of little or no worth to you. Just because you can't use information doesn't make it wrong, though. There are plenty of people in the world to whom this type of optimization matters.
The CS courses are presumably supposed to impart knowledge about what types of problems exist with parallelization. The same underlying problem, for example, also exists for distributing work to multiple CPUs, or to multiple machines. MapReduce, for example, is pretty much the same principle applied at a much higher level of abstraction - and probable about the level of abstraction that matters to you if you see RDBMS as the major bottlenecks in your experience.
Let's look at a single thing to do first and ignore parallel.
These days processors are incredibly fast at executing instructions on register values. The bottleneck isn't CPU any longer, it's loading data from main memory into the CPU caches for the most part. That's simplifying things a lot, but let's keep it at that.
With the example I've given, you've got two ints per struct, and a reasonably large number of these structs. The 200 I've given was just an example. You've also got a problem that involves only one of those ints, say, finding the highest in your set. Because you're loading both ints into the cache, but only need half of them, you'll be forced to perform twice as many loads than if you had two arrays of ints.
Now add a second problem; say, calculate the sum of the other ints. The crucial part is that one of these problems may take longer than the other to execute. That means, that at the point where one piece of code is done with the contents of a cache line, it'll try and replace it with the next chunk of data. The first problem, however, still needs the first chunk of data, so will cause this to load into cache the next time it executes. Instead of having "just" twice as many loads as you need, you might end up having hundreds.
This is not an unlikely scenario. The CPU caches will get filled with data from main memory as it's requested, i.e. when the first int is accessed for solving the first problem. When the CPU switches to processing the second problem, the data is already in cache and not loaded into a separate cache page. Unless the problems are solved at *exactly* the same speed, i.e. both problems will cause the next page of data at the same time, you *will* run into this issue.
Keep the two data sets in two separate arrays, and you'll use two cache lines. But they can be flushed and re-filled independently from each other, leading to fewer loads.
This sort of problem doesn't occur for every type of parallelization, mind you. If you try to parallelize by offloading two pieces of work to two different machines, it's not an issue. If you've got a single problem to solve that covers both ints, you don't have that problem - you can still paralellize, and parallelize pretty well, by running two hardware threads that each process half of the data set. And so on.
The point is that by getting too used to thinking in terms of arrays of structs instead of several separate arrays, you pretty much prevent yourself from solving certain parallelization problems efficiently. It's not that this *must* be bad, it's that it *can* be bad. But if you think in terms of arrays of structs, you're unlikely to even know.
I probably should've posted this straight away, but I would recommend two pieces of reading:
- http://lwn.net/Articles/250967/ (all parts) gives a good idea of all the sorts of effects that memory layout can have on your program's performance, and what you can do about it (to the degree that you can).
- http://www.slideshare.net/naughty_dog/multiprocessor-game-loops-lessons-from-uncharted-2-among-thieves specifically speaks about how to improve parallel processing efficiency by (amongst other things) doing what I wrote about above.
Linking > repeating :D
See, I don't even mind whether assembly or OOP in a high level language gets taught first. Either way, it helps to learn both to master all aspects of programming.
Personally, I'd prefer to start with assembly, but I've met plenty of people who were sufficiently confused by higher level programming languages that that wouldn't have been useful for them. And to be fair, plenty of programmers will never need to understand assembly, but still earn a decent living and contribute to the state of the art in other ways.
It really depends what you want to achieve. Get many people ready to earn a living? Might as well start with OOP. Get programmers to as high a level of understanding as possible? Probably start with assembly, then.
No, but reading helps. I did not say "this is OOP" anywhere.
One of the unintended consequences of OOP is that data tends to be laid out in memory in a similar fashion as I showed, which in turn is less than ideal for efficient parallelization of some tasks. That's all I said.
My point is that the struct you showed represents not a drawback of OOP, but an advantage that is lost in a procedural approach like that, which is the separation between the data layout and the code using the data structure, enabling changes to the data layout at any time without affecting existing code.
We're talking about parallelism here. You might have a point when talking about OOP in general, but when it comes to parallelizing code, this can be a huge drawback to efficiency. That's all I said, that's all I care about for the purposes of this conversation.
It's a problem that exists with certain approaches to creating parallel software, and has little to do with your programming language of choice in the first instance. Well, some languages don't let you control the layout of data in memory, for better or worse, so your choice does play a role... but it's mostly a question of paradigms than languages.
I gave an example in Haskell exactly because it follows different paradigm, being functional instead of OO.
Indeed. Nobody says that other paradigms might not have similar problems. But a purely procedural approach wouldn't necessarily.
The OOP paradigm is problematic for parallel programming because it suggests the inefficient approach; it doesn't require you to write inefficient code, nor does it prevent you from writing efficient code. It's very unlikely that an inexperienced programmer will chose an approach that is in conflict with the paradigm they were taught, though.
But I don't see how OOP suggests the inefficient approach any more than other paradigms.
It suggests that you think of your data in terms of conglomerates of related data items (structures) first, and consider collections (lists, arrays) of such conglomerates second. Many times, parallelization is best achieved by picking these apart into one or more collections of non-conglomerated data. OOP practically forces you to think in terms of conglomerated data, though.
Well, first that's not OOP.
No, but reading helps. I did not say "this is OOP" anywhere.
One of the unintended consequences of OOP is that data tends to be laid out in memory in a similar fashion as I showed, which in turn is less than ideal for efficient parallelization of some tasks. That's all I said.
Second, I don't see how that's not a problem in any other language. For example, in an Haskell tutorial on haskell.org, they show you the type:
type AssocList a b = [(a,b)]
Which is basically the same as the first struct.
It's a problem that exists with certain approaches to creating parallel software, and has little to do with your programming language of choice in the first instance. Well, some languages don't let you control the layout of data in memory, for better or worse, so your choice does play a role... but it's mostly a question of paradigms than languages.
The OOP paradigm is problematic for parallel programming because it suggests the inefficient approach; it doesn't require you to write inefficient code, nor does it prevent you from writing efficient code. It's very unlikely that an inexperienced programmer will chose an approach that is in conflict with the paradigm they were taught, though.
That's quite a statement. May I respond by saying that, apparently, you will never write efficient parallel code?
It's anti-parallel because it invites you to do this:
struct foo {
int a;
int b;
};
foo asdf[200];
Instead of:
struct asdf {
int a[200];
int b[200];
};
The data layout in the first case does not exactly lend itself to efficiently processing all a in parallel to all b.
As with most programming paradigms, if you understand their limitations, you can work around them. But they do suggest certain ways of structuring code that may not be good for all applications.
I don't see why it should be removed, it should be 'complimented' instead ....
Oh java, your polymorphism is awesome.
You flatter me! I don't even know multiple inheritance!
... as people claiming OO is the only way forward out of the mire of procedural programming.
Tools, jobs, you know the drill *sigh*
Ah, right, people already caught that :D
Google translate suggests that this is not, in fact, a third explosion, but an explosion at the third reactor core. Which I've seen on the news a few hours ago. So it's the second explosion. Could anyone with better understanding of Japanese confirm?
One word: gatekeeper.
Of course any platform that allows manufacturers to act as gatekeepers is preferred. Duh.
Nothing wrong with de-facto standards, if they're fully open.
Look at e.g. the Python programming language. The CPython implementation is the de-facto standard implementation, and the language specs actually refer (or used to) to the implementation saying if in doubt, that implementation wins.
Yet there are other, mostly compatible Python implementations out there, and nothing - not patents, nor secrets - stops you from starting a new one.
Yes. Yes I did. And IMO Lego pieces are worse, on the whole.
Problems start when the players melt dice into shivs...
... how is that a surprise? Are you surprised that Americans are, on average, more intelligent than you thought? Shame on you!
Yes, Wikipedia has this.
The whitepaper examines the permissions apps request, not the actions apps perform.
Sadly requested permissions are not nearly as good an indicator for potential threats as one might think. In my own app, for example, I require the permission to read contact data - there is a use-case for that. However, that in no way implies that the app e.g. harvests email addresses for a spam service. Which it easily could, with that permission.
Hey, I had tons of invites, perhaps we could've done that before... but nobody asked for them for some reason.
The discussion about whether or not is a word is what seems like a waste of effort to me.
But my previous comment wasn't meant to be a call for people to use the word "malamanteau", it was a call for people to use whatever words they like. That's what keeps language alive and kicking.
Just use the damn word; if it happens often enough, then Wikipedia can rightfully include it and the discussion is over.
Damn! I'm running Plan9 here!
... Duke Nukem Forever has ALSO been released.