Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #83341 > unrolled thread
| Started by | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| First post | 2022-03-20 18:04 +0100 |
| Last post | 2022-05-05 12:16 -0700 |
| Articles | 20 on this page of 29 — 6 participants |
Back to article view | Back to comp.lang.c++
speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-03-20 18:04 +0100
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-03-20 18:08 +0100
Re: speed of unaligned accesses that cross page-boundaries scott@slp53.sl.home (Scott Lurndal) - 2022-03-20 18:12 +0000
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-03-20 19:36 +0100
Re: speed of unaligned accesses that cross page-boundaries "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2022-03-20 16:13 -0700
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-03-21 06:58 +0100
Re: speed of unaligned accesses that cross page-boundaries scott@slp53.sl.home (Scott Lurndal) - 2022-03-21 14:49 +0000
Re: speed of unaligned accesses that cross page-boundaries Juha Nieminen <nospam@thanks.invalid> - 2022-03-21 05:59 +0000
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-03-21 08:56 +0100
Re: speed of unaligned accesses that cross page-boundaries scott@slp53.sl.home (Scott Lurndal) - 2022-03-21 14:53 +0000
Re: speed of unaligned accesses that cross page-boundaries scott@slp53.sl.home (Scott Lurndal) - 2022-03-21 16:59 +0000
Re: speed of unaligned accesses that cross page-boundaries Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-04-18 20:59 -0700
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-19 06:45 +0200
Re: speed of unaligned accesses that cross page-boundaries Juha Nieminen <nospam@thanks.invalid> - 2022-04-19 12:51 +0000
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-19 15:17 +0200
Re: speed of unaligned accesses that cross page-boundaries scott@slp53.sl.home (Scott Lurndal) - 2022-04-19 14:11 +0000
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-19 16:15 +0200
Re: speed of unaligned accesses that cross page-boundaries "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2022-04-27 01:52 -0700
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-27 20:02 +0200
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-28 08:19 +0200
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-28 12:19 +0200
Re: speed of unaligned accesses that cross page-boundaries "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2022-04-28 16:00 -0700
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-29 05:52 +0200
Re: speed of unaligned accesses that cross page-boundaries "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2022-05-04 18:06 -0700
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-05 06:13 +0200
Re: speed of unaligned accesses that cross page-boundaries "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2022-05-04 21:27 -0700
Re: speed of unaligned accesses that cross page-boundaries Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-05 07:37 +0200
Re: speed of unaligned accesses that cross page-boundaries Öö Tiib <ootiib@hot.ee> - 2022-05-05 04:34 -0700
Re: speed of unaligned accesses that cross page-boundaries "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2022-05-05 12:16 -0700
Page 1 of 2 [1] 2 Next page →
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-03-20 18:04 +0100 |
| Subject | speed of unaligned accesses that cross page-boundaries |
| Message-ID | <t17mqk$cj4$1@dont-email.me> |
I just wanted to measure the performance of unaligned accesses.
For accesses within a page the difference was below the measurement
error. Then I read that some processors put a penalty on unaligned
accesses that cross page-boundaries. So I wrote a little benchmark
that tries to measure this. But for my PCs, a Ryzen Threadripper
3990X, a Ryzen 7 1800X and a Phenom X4 945 all measurements were
also within the measurement error.
So I'm interested if someone out there has a PC where unaligned
accesses crossing a page has a performance penalty. So here's the
benchmark in C++20:
#if defined(_MSC_VER)
#include <Windows.h>
#elif defined(__unix__)
#include <unistd.h>
#endif
#include <iostream>
#include <vector>
#include <cstdint>
#include <chrono>
#include <atomic>
using namespace std;
using namespace chrono;
using namespace chrono_literals;
using T = uint64_t;
atomic<T> aSum;
int main()
{
auto bench = [&]<typename T>()
requires is_scalar_v<T>
{
auto probe = [&]( atomic<T> *pAT ) -> double
{
T sum = 0;
size_t rounds = 0;
nanoseconds nsSum( nanoseconds( 0 ) );
do
{
constexpr size_t INTERVAL = 1'000'000;
auto start = high_resolution_clock::now();
for( size_t r = INTERVAL; r--; )
sum += pAT->load( memory_order_relaxed );
nsSum += duration_cast<nanoseconds>( high_resolution_clock::now() -
start );
rounds += INTERVAL;
} while( nsSum < 250ms );
::aSum = sum;
return (double)(ptrdiff_t)rounds / (int64_t)nsSum.count();
};
auto getPageSize = []() -> size_t
{
#if defined(_MSC_VER)
SYSTEM_INFO si;
GetSystemInfo( &si );
return si.dwPageSize;
#elif defined(__unix__)
return (size_t)sysconf( _SC_PAGESIZE );
#endif
};
size_t pageSize = getPageSize();
vector<char> vec( 0x1000 + sizeof(T) );
auto align_ptr = [&]( char *p ) { return (char *)((size_t)(p +
pageSize) & ~(pageSize - 1)); };
atomic<T> *aligned = (atomic<T> *)align_ptr( &vec.front() );
double tUnaligned = probe( aligned - 1 ), tAligned = probe( aligned );
cout << (int)(tUnaligned / tAligned * 100.0 + 0.5) << "%" << endl;
};
bench.operator ()<T>();
}
Please post your results here.
[toc] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-03-20 18:08 +0100 |
| Message-ID | <t17n38$i5j$1@dont-email.me> |
| In reply to | #83341 |
> vector<char> vec( 0x1000 + sizeof(T) );
> auto align_ptr = [&]( char *p ) { return (char *)((size_t)(p +
> pageSize) & ~(pageSize - 1)); };
vector<char> vec( pageSize + sizeof(T) );
auto align_ptr = [&]( char *p ) { return (char *)((size_t)(p +
pageSize) & -(ptrdiff_t)pageSize); };
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2022-03-20 18:12 +0000 |
| Message-ID | <%7KZJ.160624$z688.76310@fx35.iad> |
| In reply to | #83341 |
Bonita Montero <Bonita.Montero@gmail.com> writes: >I just wanted to measure the performance of unaligned accesses. >For accesses within a page the difference was below the measurement >error. Then I read that some processors put a penalty on unaligned >accesses that cross page-boundaries. If the second page misses in the TLB, there will be a TLB fill penalty which for an application running in a virtual machine will require 23 memory accesses to walk the page table (anywhere from 3 to 5 for bare-metal translation table walks depending on page size). On a TLB Hit, there still may be a latency hit to obtain the cache line for the first line of the second page. Both of these will only hit when the relevent conditions exist, so they'll be difficult to measure without access to the TLB and cache flush instruction(s) on your target architecture.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-03-20 19:36 +0100 |
| Message-ID | <t17s7n$q9p$1@dont-email.me> |
| In reply to | #83345 |
> If the second page misses in the TLB, there will be a TLB
> fill penalty which for an application running in a virtual
> machine will require 23 memory accesses to walk the page
> table (anywhere from 3 to 5 for bare-metal translation table
> walks depending on page size).
I'm measuring the penalty while crossing a page-boundary where
both pages are in the TLB - so this is irrelevant here.
> On a TLB Hit, there still may be a latency hit to obtain
> the cache line for the first line of the second page.
With all my three PCs the time for crossing a page-boundary, an
aligned access and an unaligned access within a page are all the
same.
I first thought that with the access crossing a page-boundary the
CPU does check for duplicate loads in the queue for outstanding
OoO-loads and satisfies them all from the same load. So I modified
my code a bit to have a configurable numer of accesses to different
page-boundaries:
#if defined(_WIN32)
#include <Windows.h>
#elif defined(__unix__)
#include <unistd.h>
#endif
#include <iostream>
#include <vector>
#include <cstdint>
#include <chrono>
#include <atomic>
#include <string_view>
using namespace std;
using namespace chrono;
using namespace chrono_literals;
using T = uint64_t;
atomic<T> aSum;
int main()
{
#if defined(_WIN32)
SetThreadAffinityMask( GetCurrentThread(), 1 );
if( !SetThreadPriority( GetCurrentThread(),
THREAD_PRIORITY_TIME_CRITICAL ) )
SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST );
#endif
auto bench = [&]<typename T, size_t NBoundaries>()
requires is_scalar_v<T>
{
auto probe = [&]( vector<void *> const &addrs ) -> double
{
T sum = 0;
size_t rounds = 0;
nanoseconds nsSum( nanoseconds( 0 ) );
size_t
interval = 1'000'000 / addrs.size(),
roundsPerInterval = interval * addrs.size();
do
{
auto start = high_resolution_clock::now();
for( size_t r = interval; r--; )
for( void *p : addrs )
sum += ((atomic<T> *)p)->load( memory_order_relaxed );
nsSum += duration_cast<nanoseconds>( high_resolution_clock::now() -
start );
rounds += roundsPerInterval;
} while( nsSum < 250ms );
::aSum = sum;
return (double)(ptrdiff_t)rounds / (int64_t)nsSum.count();
};
auto getPageSize = []() -> size_t
{
#if defined(_WIN32)
SYSTEM_INFO si;
GetSystemInfo( &si );
return si.dwPageSize;
#elif defined(__unix__)
return (size_t)sysconf( _SC_PAGESIZE );
#endif
};
size_t pageSize = getPageSize();
auto allocPages = [&]( size_t nPages ) -> void *
{
#if defined(_WIN32)
return VirtualAlloc( nullptr, nPages * pageSize, MEM_RESERVE |
MEM_COMMIT, PAGE_READWRITE );
#elif defined(__unix__)
return mmap( nullptr, nPages * pageSize, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0 );
#endif
};
void *p = allocPages( NBoundaries + 1 );
vector<void *> addrs;
double times[3];
ptrdiff_t offset = -1;
do
{
addrs.resize( 0 );
addrs.reserve( NBoundaries );
for( size_t b = 0; b != NBoundaries; ++b )
addrs.emplace_back( (void *)((size_t)p + pageSize + offset) );
times[offset + 1] = probe( addrs );
} while( ++offset <= 1 );
auto pct = []( double tRel, double tBase ) -> int { return (int)((tRel
/ tBase - 1.0) * 100.0 + 0.5); };
cout << "crossing page boundaries: " << pct( times[0], times[1] ) <<
"%" << endl;
cout << "within page: " << pct( times[2], times[1] ) <<
"%" << endl;
};
bench.operator ()<T, 64>();
}
But this code also gives me the same access-times for unaligned accesses
within a page, aligned accesses and accesses crossing a page-boundary
for all my three PCs.
> Both of these will only hit when the relevent conditions
> exist, so they'll be difficult to measure without access
> to the TLB and cache flush instruction(s) on your target
> architecture.
The TLB privilege-checks are done on every acccess, even when the
address is scoped by the TLB.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2022-03-20 16:13 -0700 |
| Message-ID | <t18ceo$tbu$1@dont-email.me> |
| In reply to | #83341 |
On 3/20/2022 10:04 AM, Bonita Montero wrote: > I just wanted to measure the performance of unaligned accesses. > For accesses within a page the difference was below the measurement > error. Then I read that some processors put a penalty on unaligned > accesses that cross page-boundaries. So I wrote a little benchmark > that tries to measure this. But for my PCs, a Ryzen Threadripper > 3990X, a Ryzen 7 1800X and a Phenom X4 945 all measurements were > also within the measurement error. > So I'm interested if someone out there has a PC where unaligned > accesses crossing a page has a performance penalty. So here's the > benchmark in C++20: [...] Iirc, an unaligned atomic RMW would trigger a bus lock. Actually, somebody used it to trigger a system wide membar, take a look at QPI quiescence: https://chaelim.github.io/2017-04-29-qpi-quiescence I cannot find the damn original paper right now, but Windows API actually has an API that allows one to build asymmetric synchronization: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-flushprocesswritebuffers
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-03-21 06:58 +0100 |
| Message-ID | <t1945v$rc3$1@dont-email.me> |
| In reply to | #83350 |
> Iirc, an unaligned atomic RMW would trigger a bus lock. Actually, > somebody used it to trigger a system wide membar, take a look at QPI > quiescence: That's a completely different topic.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2022-03-21 14:49 +0000 |
| Message-ID | <Uf0_J.321422$Rza5.100496@fx47.iad> |
| In reply to | #83350 |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes: >On 3/20/2022 10:04 AM, Bonita Montero wrote: >> I just wanted to measure the performance of unaligned accesses. >> For accesses within a page the difference was below the measurement >> error. Then I read that some processors put a penalty on unaligned >> accesses that cross page-boundaries. So I wrote a little benchmark >> that tries to measure this. But for my PCs, a Ryzen Threadripper >> 3990X, a Ryzen 7 1800X and a Phenom X4 945 all measurements were >> also within the measurement error. >> So I'm interested if someone out there has a PC where unaligned >> accesses crossing a page has a performance penalty. So here's the >> benchmark in C++20: >[...] > >Iirc, an unaligned atomic RMW would trigger a bus lock. Actually, >somebody used it to trigger a system wide membar, take a look at QPI >quiescence: The keyword there is 'atomic' which requires the lock prefix on x86. Note that there are other cases where Intel and AMD processors will assert the system-wide bus lock - for example, if a competing spin lock doesn't win for some period of time, the core will assert the bus lock to ensure forward progress. This can seriously impact performance[*], as we found out when we put one of our large SMP machines at LLNL a couple decades ago. [*] granted, this as a degenerate case tested for explictly by the LLNL researchers where all 256 cores were spinning on the same spinlock in a NUMA machine where there was a 10x difference in latency between local and remote memory.
[toc] | [prev] | [next] | [standalone]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-03-21 05:59 +0000 |
| Message-ID | <t1947l$1jv3$2@gioia.aioe.org> |
| In reply to | #83341 |
Bonita Montero <Bonita.Montero@gmail.com> wrote: > I just wanted to measure the performance of unaligned accesses. > For accesses within a page the difference was below the measurement > error. Then I read that some processors put a penalty on unaligned > accesses that cross page-boundaries. So I wrote a little benchmark > that tries to measure this. But for my PCs, a Ryzen Threadripper > 3990X, a Ryzen 7 1800X and a Phenom X4 945 all measurements were > also within the measurement error. IIRC both Intel and AMD got rid of the unaligned access penalty at some point (relatively recently). You would need an older CPU in order to get the penalty. (Btw, I assume you know that unaligned access is standardized as UB.)
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-03-21 08:56 +0100 |
| Message-ID | <t19b3p$hk$1@dont-email.me> |
| In reply to | #83354 |
> IIRC both Intel and AMD got rid of the unaligned access penalty > at some point (relatively recently). You would need an older CPU > in order to get the penalty. I don't wanted to measure the penalty of just unaligned accesses but those unalaigned acccesses that cross a page-boundary. In my first code in this thread I repeatedly accessed the same word which crosses a page-boundary and there was no difference in access times between such accesses and aligned accesses. Then I thought the processor could bypass further loads or join multiple loads in the load-queue so that I won't notice the penalty of the first accesss. So I accessed a row of addresses which crossed a page-boundary in my second code; but this code had a bug and also didn't measure a difference. I corrected it and with this code I had a penalty of nearly 50% when accessing an unaligned address crossing a page -boundary. So I was right to assume that my CPUs, even my old 2009 Phenom II X4 945 all join multiple loads to the same address in the load-queue !
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2022-03-21 14:53 +0000 |
| Message-ID | <mj0_J.321728$Rza5.183381@fx47.iad> |
| In reply to | #83354 |
Juha Nieminen <nospam@thanks.invalid> writes: >Bonita Montero <Bonita.Montero@gmail.com> wrote: >> I just wanted to measure the performance of unaligned accesses. >> For accesses within a page the difference was below the measurement >> error. Then I read that some processors put a penalty on unaligned >> accesses that cross page-boundaries. So I wrote a little benchmark >> that tries to measure this. But for my PCs, a Ryzen Threadripper >> 3990X, a Ryzen 7 1800X and a Phenom X4 945 all measurements were >> also within the measurement error. > >IIRC both Intel and AMD got rid of the unaligned access penalty >at some point (relatively recently). You would need an older CPU >in order to get the penalty. The barrel shifter penalty is gone. However, it is unavoidable that such an access will need to access _two_ L1D cache lines, and the hardware thread/core cannot do both accesses in parallel. Note that Load-to-use penalties on x86 processors are about 4 clocks when they hit in L1D. Much of that additional latency will be hidden by out-of-order execution, unless there is an immediate dependency upon the value loaded.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2022-03-21 16:59 +0000 |
| Message-ID | <fa2_J.255665$mF2.13892@fx11.iad> |
| In reply to | #83360 |
scott@slp53.sl.home (Scott Lurndal) writes: >Juha Nieminen <nospam@thanks.invalid> writes: >>Bonita Montero <Bonita.Montero@gmail.com> wrote: >>> I just wanted to measure the performance of unaligned accesses. >>> For accesses within a page the difference was below the measurement >>> error. Then I read that some processors put a penalty on unaligned >>> accesses that cross page-boundaries. So I wrote a little benchmark >>> that tries to measure this. But for my PCs, a Ryzen Threadripper >>> 3990X, a Ryzen 7 1800X and a Phenom X4 945 all measurements were >>> also within the measurement error. >> >>IIRC both Intel and AMD got rid of the unaligned access penalty >>at some point (relatively recently). You would need an older CPU >>in order to get the penalty. > >The barrel shifter penalty is gone. However, it is unavoidable >that such an access will need to access _two_ L1D cache lines, and >the hardware thread/core cannot do both accesses in parallel. Note that >Load-to-use penalties on x86 processors are about 4 clocks when >they hit in L1D. Much of that additional latency will be hidden >by out-of-order execution, unless there is an immediate dependency >upon the value loaded. Clock Operation ----- ----------------- 1 CAM the VA against the L1D TLB to get the PA [Assumes TLB hit] 2 Using bits from the PA to select the set, CAM the ways [Assumes L1D hit] 3 Load the data from SRAM onto the core bus. 4 load the data from the core bus into the register This needs to be done for both cache lines, sequentially. Now, given that BM is using the C++ compiler, it is likely the compiler is hoisting the load and/or reordering instructions to cover that expected latency. Adding in the cores out-of-order execution, I doubt that BM can derive any valid latency information relative to misaligned cache/page crossing accesses using C++. Note that an access that crosses a page boundary must by definition also cross a cache line boundary.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2022-04-18 20:59 -0700 |
| Message-ID | <865yn5afkq.fsf@linuxsc.com> |
| In reply to | #83354 |
Juha Nieminen <nospam@thanks.invalid> writes: > Bonita Montero <Bonita.Montero@gmail.com> wrote: > >> I just wanted to measure the performance of unaligned accesses. >> For accesses within a page the difference was below the measurement >> error. Then I read that some processors put a penalty on unaligned >> accesses that cross page-boundaries. So I wrote a little benchmark >> that tries to measure this. But for my PCs, a Ryzen Threadripper >> 3990X, a Ryzen 7 1800X and a Phenom X4 945 all measurements were >> also within the measurement error. > > IIRC both Intel and AMD got rid of the unaligned access penalty > at some point (relatively recently). You would need an older CPU > in order to get the penalty. > > (Btw, I assume you know that unaligned access is standardized as UB.) I assume BM is talking about unaligned access in the actual machine. An access that is unaligned in the actual machine may be an aligned access as far as the abstract machine is concerned.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-04-19 06:45 +0200 |
| Message-ID | <t3leom$neh$1@dont-email.me> |
| In reply to | #83354 |
Am 21.03.2022 um 06:59 schrieb Juha Nieminen: > Bonita Montero <Bonita.Montero@gmail.com> wrote: >> I just wanted to measure the performance of unaligned accesses. >> For accesses within a page the difference was below the measurement >> error. Then I read that some processors put a penalty on unaligned >> accesses that cross page-boundaries. So I wrote a little benchmark >> that tries to measure this. But for my PCs, a Ryzen Threadripper >> 3990X, a Ryzen 7 1800X and a Phenom X4 945 all measurements were >> also within the measurement error. > > IIRC both Intel and AMD got rid of the unaligned access penalty > at some point (relatively recently). ... No, for a long time. Unaligned accesses are quite common for I/O purposes. The only unaligned access that is inefficient is when you cross a page-boundary (almost twice the lantency).
[toc] | [prev] | [next] | [standalone]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-04-19 12:51 +0000 |
| Message-ID | <t3mb81$ndi$1@gioia.aioe.org> |
| In reply to | #83634 |
Bonita Montero <Bonita.Montero@gmail.com> wrote: >> IIRC both Intel and AMD got rid of the unaligned access penalty >> at some point (relatively recently). ... > > No, for a long time. Unaligned accesses are quite common for > I/O purposes. The only unaligned access that is inefficient > is when you cross a page-boundary (almost twice the lantency). AFAIK Intel got rid of the penalty with the Sandy Bridge architecture (i5-2400, i5-2500, i7-2600, i7-2700, etc). While that was 11 years ago, that's "relatively recently" considering Intel's entire history.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-04-19 15:17 +0200 |
| Message-ID | <t3mcp2$h3$1@dont-email.me> |
| In reply to | #83638 |
Am 19.04.2022 um 14:51 schrieb Juha Nieminen: > Bonita Montero <Bonita.Montero@gmail.com> wrote: >>> IIRC both Intel and AMD got rid of the unaligned access penalty >>> at some point (relatively recently). ... >> >> No, for a long time. Unaligned accesses are quite common for >> I/O purposes. The only unaligned access that is inefficient >> is when you cross a page-boundary (almost twice the lantency). > > AFAIK Intel got rid of the penalty with the Sandy Bridge architecture > (i5-2400, i5-2500, i7-2600, i7-2700, etc). While that was 11 years ago, > that's "relatively recently" considering Intel's entire history. Maybe you're right. I just ran my unaligned benchmark on a old Phenom X4 945 under Ubuntu 20.04: 0x200: 50% 0x400: 51% 0x800: 50% 0x1000: 50% 0x2000: 50% 0x4000: 59% 0x8000: 59% 0x10000: 69% 0x20000: 95% 0x40000: 95% 0x80000: 94% 0x100000: 90% 0x200000: 92% 0x400000: 92% 0x800000: 91% 0x1000000: 92% 0x2000000: 91% 0x4000000: 92% 0x8000000: 92% The percentage is the speed of unaligned accesses related to aligned accesses at the same block-size. With larger block-sizes the share of the memory or higher level cache access time becomes a larger part of the access time and as 64 bytes are fetched for a whole cacheline and the access mostly fetches only one cacheline.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2022-04-19 14:11 +0000 |
| Message-ID | <cqz7K.73579$e%.42450@fx36.iad> |
| In reply to | #83634 |
Bonita Montero <Bonita.Montero@gmail.com> writes: >Am 21.03.2022 um 06:59 schrieb Juha Nieminen: >> >> IIRC both Intel and AMD got rid of the unaligned access penalty >> at some point (relatively recently). ... > > >No, for a long time. Unaligned accesses are quite common for >I/O purposes. Actually, they are very uncommon for I/O purposes. 99.99% of all MMIO accessess are aligned. 99.9999% of all DMA accesses are aligned. >The only unaligned access that is inefficient >is when you cross a page-boundary (almost twice the lantency). Actually, it's when you cross a cache line boundary that the latency starts to increase. A TLB miss may add additional latency.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-04-19 16:15 +0200 |
| Message-ID | <t3mg5e$pbb$1@dont-email.me> |
| In reply to | #83640 |
> Actually, they are very uncommon for I/O purposes. ... Data structures for file or network-I/O often have unaligned basic types. > Actually, it's when you cross a cache line boundary that > the latency starts to increase. ... No, absolutely no.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2022-04-27 01:52 -0700 |
| Message-ID | <t4b07g$ccl$1@dont-email.me> |
| In reply to | #83641 |
On 4/19/2022 7:15 AM, Bonita Montero wrote: >> Actually, they are very uncommon for I/O purposes. ... > > Data structures for file or network-I/O often have unaligned > basic types. > >> Actually, it's when you cross a cache line boundary that >> the latency starts to increase. ... > > No, absolutely no. > Straddling a cache line is very bad... NO, try not to do it!
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-04-27 20:02 +0200 |
| Message-ID | <t4c0fh$hrg$1@dont-email.me> |
| In reply to | #83806 |
Am 27.04.2022 um 10:52 schrieb Chris M. Thomasson: > On 4/19/2022 7:15 AM, Bonita Montero wrote: >>> Actually, they are very uncommon for I/O purposes. ... >> >> Data structures for file or network-I/O often have unaligned >> basic types. >> >>> Actually, it's when you cross a cache line boundary that >>> the latency starts to increase. ... >> >> No, absolutely no. >> > > Straddling a cache line is very bad... NO, try not to do it! That's not a problem with x86- and ARMv8-CPUs for a long time. Only crossing a page-boundary includes two privilege-checks.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-04-28 08:19 +0200 |
| Message-ID | <t4dbkr$n2g$1@dont-email.me> |
| In reply to | #83806 |
Try this:
#if defined(_WIN32)
#include <Windows.h>
#elif defined(__unix__)
#include <sys/mman.h>
#include <pthread.h>
#endif
#include <iostream>
#include <string_view>
#include <memory>
#include <thread>
#include <vector>
#include <latch>
#include <atomic>
#include <chrono>
#include <semaphore>
using namespace std;
using namespace chrono;
int main()
{
constexpr size_t
#if defined(__cpp_lib_hardware_interference_size)
CL_SIZE = hardware_destructive_interference_size,
#else
CL_SIZE = 64,
#endif
BLOCK_SIZE = 0x1000,
ROUNDS = 10'000'000;
#if defined(_WIN32)
char *begin = (char *)VirtualAlloc( nullptr, BLOCK_SIZE, MEM_RESERVE |
MEM_COMMIT, PAGE_READWRITE );
#elif defined(__unix__)
char *begin = (char *)mmap( nullptr, BLOCK_SIZE, PROT_READ |
PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0 );
#endif
char *end = begin + BLOCK_SIZE;
atomic_uint readyCountDown;
binary_semaphore semReady( false );
counting_semaphore semRun( 0 );
atomic_uint synch;
atomic_uint64_t nsSum;
auto theThread = [&]( ptrdiff_t offset )
{
if( readyCountDown.fetch_sub( 1, memory_order_relaxed ) == 1 )
semReady.release();
semRun.acquire();
if( synch.fetch_sub( 1, memory_order_relaxed ) != 1 )
while( synch.load( memory_order_relaxed ) );
auto start = high_resolution_clock::now();
for( size_t r = ROUNDS; r--; )
for( char *p = begin + CL_SIZE; p != end; p += CL_SIZE )
(void)((atomic_uint &)p[offset]).load( memory_order_relaxed );
nsSum.fetch_add( (uint64_t)duration_cast<nanoseconds>(
high_resolution_clock::now() - start ).count(), memory_order_relaxed );
};
unsigned hc = thread::hardware_concurrency();
vector<jthread> threads;
threads.reserve( 2 );
for( ptrdiff_t offset = 0; offset >= -1; --offset )
{
cout << "offset: " << offset << endl;
for( unsigned nThreads = 1; nThreads <= 2; ++nThreads )
{
readyCountDown.store( nThreads, memory_order_relaxed );
synch.store( nThreads, memory_order_relaxed );
nsSum.store( 0, memory_order_relaxed );
for( unsigned t = 0; t != nThreads; ++t )
threads.emplace_back( theThread, offset );
semReady.acquire();
auto setAff = []( jthread::native_handle_type handle, unsigned cpu )
{
#if defined(_WIN32)
if( !SetThreadAffinityMask( handle, (DWORD_PTR)1 << cpu ) )
ExitProcess( EXIT_FAILURE );
#elif defined(__unix__)
cpu_set_t cpuSet;
CPU_ZERO(&cpuSet);
CPU_SET(cpu, &cpuSet);
if( pthread_setaffinity_np( handle, sizeof cpuSet, &cpuSet ) )
exit( EXIT_FAILURE );
#endif
};
for( size_t t = 0; t != nThreads; ++t )
setAff( threads[t].native_handle(), hc / 2 * (unsigned)t );
semRun.release( nThreads );
threads.resize( 0 );
cout << "\t" << nThreads << ": " << (double)(int64_t)nsSum.load(
memory_order_relaxed ) / ((int)nThreads * 1.0e9) << endl;
}
}
}
On my computer (Ryzen Threadripper 3990X) this shows that accesses
crossing a cacheline-boundary are only about 5% slower and it dosn't
matter if there is one or two threads accessing the memory. I thought
that with two threads the access might be slower because unaligned
accesses might occupy more than one load unit and more threads might
occupy four load units - but by CPU has only two.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c++
csiph-web