0

How can I change the data of 2 rows of an array using the swap. I write the basic change code but i want to improve performance by changing it into one line (using swap function or something like that as in the bottom of this page). my main code:

   int i,j;
    int A[50][4];
    i=5;
    j=21;
 //line 5   
    int t1 = A[j][0];
    int t2 = A[j][1];
    int t3 = A[j][2];
    int t4 = A[j][3];

    A[j][0]=A[i][0]  ;
    A[j][1]=A[i][1]  ;
    A[j][2]=A[i][2] ;
    A[j][3]=A[i][3] ;

    A[i][0] = t1;
    A[i][1] = t2;
    A[i][2] = t3;
    A[i][3] = t4;
//line 18

What I want to change: change line 5-18 in to one of the following:

A[i][] = A[j][];

or

swap (A[i] , A[j])
  • That looks like error-prone code. You'll have fun with that for many months to come... – trojanfoe Aug 21 '13 at 10:32
  • 1
    [`std::swap`](http://en.cppreference.com/w/cpp/algorithm/swap)? – Some programmer dude Aug 21 '13 at 10:34
  • If performance is really an issue, you could probably accomplish this by wrapping the array in a class, using some sort of pointer assignment internally to control what row X really points to, and exposing getter functions for the elements externally. That gives me a headache to think about, but its along the lines of spin_eight's answer. – Kindread Aug 21 '13 at 10:39

4 Answers4

5

Just use std::swap, it has an overload for arrays. In your case:

std::swap( A[i] , A[j] );

Note that the type of A[i] is int[4], wich fits perfectly in that overload.

EDIT: If you can't use C++11 features, std::swap_ranges could be an option:

std::swap_ranges( A[i] , A[i] + 4 , A[j] );
Manu343726
  • 13,969
  • 4
  • 40
  • 75
  • 3
    And in the absence of C++11 support, then `std::swap_ranges`. could be an option. – juanchopanza Aug 21 '13 at 10:39
  • Thanks @juanchopanza I have added that into the answer. – Manu343726 Aug 21 '13 at 10:50
  • He asked about performance. your implementation does not really give any performance improvement. It is just safe and standard way for swap operations. – Simple Fellow Sep 19 '13 at 07:18
  • @SimpleFellow thats not true: `std::swap` uses the most convenient way to copy the data. It the best case, `memcpy`. See my comments in spin_eight's answer. – Manu343726 Sep 19 '13 at 09:33
  • @SimpleFellow consider this in the future: **First: You will never write solutions more efficient than the provided by the standard library**. Standard library algorithms are dessigned to explote that kind of low-level tricks, and are dessigned to be **easily optimizable by the compiler**. To allow the compiler optimize your code, **write it in the most clear way**. Its better for you (Its more readable) and for it (It understands what you are trying to do, so it could apply optimizations with no side-effects). – Manu343726 Sep 19 '13 at 09:41
  • @SimpleFellow **Second: Efficience (Performance) is heavily related to the context. Write the most clear code and profile it. When you have found the hotspots, try to optimize them. Don't waste time in parts of the code which are used in the 0,001% of the execution** – Manu343726 Sep 19 '13 at 09:44
  • @Manu343726 why argue? Open the utility header file & see how swap() is implemented Or check out my answer below for the std::swap() code. **Oh My My! you are in for a Big Shock**. There ain't no low level tricks there. It runs a for loop and performs item by item swapping calling the single item swap() function. Go see for yourself! One thing: STL Standard Template Library isn't for the "tricks". it's purpose is to provide generic functionality n save the developers from reinventing the wheel for most common tasks for which there is no help from the language itself! – Simple Fellow Sep 19 '13 at 15:50
0

Dont swap just do it in a loop:

for (int p=0; p<4; p++) {
    int t = A[j][p];
    A[j][p] = A[i][p];
    A[i][p] = t;
}
Tiago
  • 383
  • 1
  • 7
0

use another data structures, that will fit to you needs best, I propose array of pointers:

int* A[4]; for (int i = 0; i < sizeof(A) / sizeof(A[0]);++i) {A[i] = new int[50];}

using this technique you can easily swap rows by swapping pointers )

spin_eight
  • 3,925
  • 10
  • 39
  • 61
  • I think suggest error-prone manual-memory-management array of pointers instead of safe, easy to use, and cache-friendly multidimensional array is a very bad idea. – Manu343726 Aug 21 '13 at 10:42
  • @Manu343726 topic starter mentioned that he wants to improve efficiency, my code snippet provides it although I agree with you what it can be harder for somebody to implement it. As regarding you answer I think swap_ranges, suggested by juanchopanza will be more efficient solution when swapping by elements – spin_eight Aug 21 '13 at 10:47
  • be careful with you think could be a "optimization". What about cache aligment? Cache-misses? Your solution is clearly not chache-friendly, and the multidimensional array is just a chunck of continious aligned memory, wich in this case could fit perfectly in a cache line. **Be aware of premature optimization**. I provided the most elegant solution, but if you think your solution could have better performance, **profile it**. – Manu343726 Aug 21 '13 at 10:55
  • Note that you are using a for loop (Branches, branches, everywhere...), but `std::swap()` can use perfectly `memcpy` to copy the entire chunk of memory in one operation (Note that the array is of ints). – Manu343726 Aug 21 '13 at 10:57
  • @Manu343726 thanks for pointing out code weaknesses, I am not aware of cache-friendliness could you please give me some references to proper sources of information, that might be useful for me. Thnx in advance – spin_eight Aug 21 '13 at 10:58
  • No references are needed, I will try to explain: Your answer suggests to use `int*[10]`, right? That array could be obtained from a cast from a bidimansional array like `int[10][4]`, so in that case there are no cache problems. But that couldn`t be the case, because pointer-swapping has no sense at all. So your real suggestion is to use an **array of dynamic arrays**, wich is by definition non-cache-friendly: Dynamic memory is allocated anywhere on the heap, so that memory is not space-located within the rest of the array (Each dynamic array is in one sparese position) . ... – Manu343726 Aug 21 '13 at 11:20
  • ... No space-locality, cache-miss-prone. Even if you use tricks like [this](http://stackoverflow.com/a/8547993/1609356) to allocate all dynamic arrays in a continious chunk of memory, that memory is not located within the stack, so the dereferencing process has a cost (And a possible cache-miss). – Manu343726 Aug 21 '13 at 11:20
  • In the trick case im not sure if the cost of the dereferencing cache-miss is superior to the cost of copy three chuncks of memory with `memcpy`. Again, profile it. **Performance depends heavily on the context, so is better to write the most readable code and profile it to find the hotspots than gain a headache with this kind of low-level behaviour (And premature optimization) discussions.** – Manu343726 Aug 21 '13 at 11:27
-1

If you want performance improvement, this is the fastest swapping operation, faster than the stl::swap runs on standard C++ compilers.

template<typename T=int>
void swap(T* p, T* q, int size)
{
    T* ptmp = new T[size];
    memcpy(ptmp, p, sizeof(T)*size);
    memcpy(p, q, sizeof(T)*size);
    memcpy(q, ptmp, sizeof(T)*size);
    delete[] ptmp;
}

You can make it even faster by replacing the call to new with (int*)alloca(sizeof(int)*size) and commenting out the delete. But alloca is kind of limited as it uses function stack. Okay so you would call it like this:

 //line 5 
    swap(A[j], A[i]);

    //int t1 = A[j][0];
    // ... 

//line 18

This is from the documentation of std::swap():

Non-array: Constant: Performs exactly one construction and two assignments (although each of these operations works on its own complexity).

Array: Linear in N: performs a swap operation per element.

since this swap() performs operation on block of memory rather than element by element therefore it is better then std::swap(). I have confirmed the results using AQtime.

for anyone thinking about "space-locality, cache-miss-prone, cache aligment, cache friendly blah blah blah..." here it is for them:

the memcpy implementations are often written with SIMD instructions which makes it possible to shuffle 128 bits at a time. SIMD instructions are assembly instructions that can perform the same operation on each element in a vector up to 16 bytes long. That includes load and store instructions.

For people who are confused, here is how the std::swap() is implemented in utility header file VC 2012 by Microsoft

        // TEMPLATE FUNCTION swap
template<class _Ty,
    size_t _Size> inline
    void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size])
    {   // exchange arrays stored at _Left and _Right
    if (&_Left != &_Right)
        {   // worth swapping, swap ranges
        _Ty *_First1 = _Left;
        _Ty *_Last1 = _First1 + _Size;
        _Ty *_First2 = _Right;
        for (; _First1 != _Last1; ++_First1, ++_First2)
            _STD iter_swap(_First1, _First2);
        }
    }
Simple Fellow
  • 4,315
  • 2
  • 31
  • 44