DataLoopTest.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include "../testTools.h"
  2. #define INITIALIZE \
  3. for (int i = 0; i < elements; i++) { \
  4. bufferA[i] = i % 13; \
  5. bufferB[i] = i % 7; \
  6. bufferC[i] = 0; \
  7. }
  8. #define CHECK_RESULT \
  9. { \
  10. int errors = 0; \
  11. for (int i = 0; i < elements; i++) { \
  12. if (bufferC[i] != ((i % 13) * (i % 7)) + 5) { \
  13. errors++; \
  14. } \
  15. } \
  16. ASSERT(errors == 0); \
  17. }
  18. START_TEST(DataLoop)
  19. // Allocate aligned memory
  20. const int elements = 256;
  21. int32_t allocationA[elements] ALIGN16;
  22. int32_t allocationB[elements] ALIGN16;
  23. int32_t allocationC[elements] ALIGN16;
  24. // The SafePointer class will emulate the behaviour of a raw data pointer while providing full bound checks in debug mode.
  25. SafePointer<int32_t> bufferA("bufferA", allocationA, sizeof(allocationA));
  26. SafePointer<int32_t> bufferB("bufferB", allocationB, sizeof(allocationB));
  27. SafePointer<int32_t> bufferC("bufferC", allocationC, sizeof(allocationC));
  28. // Calculate C = (A * B) + 5
  29. { // Reference implementation
  30. INITIALIZE;
  31. for (int i = 0; i < elements; i++) {
  32. bufferC[i] = (bufferA[i] * bufferB[i]) + 5;
  33. }
  34. CHECK_RESULT;
  35. }
  36. { // Pointer version
  37. INITIALIZE;
  38. // Iterating pointers are created from the main pointers
  39. SafePointer<int32_t> ptrA = bufferA;
  40. SafePointer<int32_t> ptrB = bufferB;
  41. SafePointer<int32_t> ptrC = bufferC;
  42. for (int i = 0; i < elements; i++) {
  43. // *a is the same as a[0]
  44. *ptrC = *ptrA * *ptrB + 5;
  45. // Adding one to a pointer adds the size of the element type
  46. ptrA += 1;
  47. ptrB += 1;
  48. ptrC += 1;
  49. }
  50. CHECK_RESULT;
  51. }
  52. { // Pseudo vectorization (what the SIMD math actually means)
  53. INITIALIZE;
  54. for (int i = 0; i < elements - 3; i += 4) {
  55. bufferC[i + 0] = (bufferA[i + 0] * bufferB[i + 0]) + 5;
  56. bufferC[i + 1] = (bufferA[i + 1] * bufferB[i + 1]) + 5;
  57. bufferC[i + 2] = (bufferA[i + 2] * bufferB[i + 2]) + 5;
  58. bufferC[i + 3] = (bufferA[i + 3] * bufferB[i + 3]) + 5;
  59. }
  60. CHECK_RESULT;
  61. }
  62. { // SIMD version
  63. INITIALIZE;
  64. SafePointer<int32_t> ptrA = bufferA;
  65. SafePointer<int32_t> ptrB = bufferB;
  66. SafePointer<int32_t> ptrC = bufferC;
  67. for (int i = 0; i < elements - 3; i += 4) {
  68. // Read vectors
  69. I32x4 a = I32x4::readAligned(ptrA, "data loop test @ read a");
  70. I32x4 b = I32x4::readAligned(ptrB, "data loop test @ read b");
  71. // Do the calculation with 4 elements at once from i to i + 3 using SIMD operations
  72. I32x4 result = a * b + 5;
  73. // Write the result
  74. result.writeAligned(ptrC, "data loop test @ write c");
  75. // Iterate pointers
  76. ptrA += 4;
  77. ptrB += 4;
  78. ptrC += 4;
  79. }
  80. CHECK_RESULT;
  81. }
  82. END_TEST