Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

C++ Operator Multi-Versioning

Patrick_P_3
Beginner
503 Views

This is my first posting here, so I apologize if this isn't quite the right place for this question.

So I just got very interested in multiversioning in order to do some performance comparisons of instruction sets between Haswell and SandyBridge, and with functions it's a breeze, but when I tried to do the same with operators I received the following error:

internal error: assertion failed: mangled_operator_name: bad kind (shared/cfe/edgcpfe/lower_name.c, line 10192)

__attribute__ ((target("default")))
IntVec& operator+=(IntVec& v1, const IntVec& v2) {
    v1.data()[0:v1.size()] += v2.data()[0:v2.size()];
    return v1;
}

//IntVec is just short for std::vector<int>

I can't seem to find any information as to why this is invalid on the web, so I assume there must be some way to accomplish this, though everything I've tried has failed or created overhead I know shouldn't be necessary. Is it valid to try this? If so, what's the proper course? Otherwise, why is it invalid to have multiple versions of an operator for various instruction sets?

Also, if I wanted to specifically target a Xeon Phi, how would I best go about this?

0 Kudos
6 Replies
Shenghong_G_Intel
503 Views

From my understanding, this is valid and should be accepted!!

Whatever, such an error at least means a bug of compiler crash. I've reproduced it with 15.0 v2 compiler, I'll submit it to dev team to fix.

Thanks,

Shenghong

0 Kudos
Shenghong_G_Intel
503 Views

Patrick,

This issue is fixed in update 3 release, v15.0. Please upgrade and verify.

$ cat temp.cpp
#include <vector>

// this works
__attribute__ ((target("default")))
void foo() {}

// this will crash
__attribute__ ((target("default")))
void operator+=(std::vector<int>& v1, std::vector<int>& v2){
}
$ icc temp.cpp -c
$ icc -V
Intel(R) C Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.3.187 Build 20150407
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

$

Thanks,

Shenghong

0 Kudos
Patrick_P_3
Beginner
503 Views

shenghong-geng (Intel) wrote:

Patrick,

This issue is fixed in update 3 release, v15.0. Please upgrade and verify.

Thanks,

Shenghong

Oh you're gonna love this. The following version will not let me compile with an attribute on an operator with a template, BUT, the second version will. Notice the backslash on the second version, AND, I can correctly target different architectures. So, someone still has some work to do. As to the original point, I can now put an attribute on an operator, but it will not work if there is a template. Or is there a more correct way to do this?

#include <vector>
#include <iostream>

std::vector<int> data1 = {0,1,2,3,4};
std::vector<int> data2 = {5,4,3,2,1};

// this works
__attribute__ ((target("default")))
void foo() {}
	 
// this will crash
__attribute__ ((target("default")))
template <class T>
void operator+=(std::vector<T>& v1, std::vector<T>& v2){
    v1.data()[0:v1.size()] += v2.data()[0:v2.size()];
}

int main(int argc, char** argv) {
    for (auto a : data1) std::cout << a << ' ';
    std::cout << std::endl;
    for (auto b : data2) std::cout << b << ' ';
    std::cout << std::endl;
    foo();
    data1 += data2;
    for (auto c : data1) std::cout << c << ' ';
    std::cout << std::endl;
}

//gets error: temp.cpp(12): error: attributes are not allowed here
  __attribute__ ((target("default")))

//the following works

#include <vector>
#include <iostream>

std::vector<int> data1 = {0,1,2,3,4};
std::vector<int> data2 = {5,4,3,2,1};

// this works and can target any desired attribute
__attribute__ ((target("default")))
void foo() {}
    
// this will crash\
__attribute__ ((target("default")))
template <class T>
void operator+=(std::vector<T>& v1, std::vector<T>& v2){
    v1.data()[0:v1.size()] += v2.data()[0:v2.size()];
}

int main(int argc, char** argv) {
    for (auto a : data1) std::cout << a << ' ';
    std::cout << std::endl;
    for (auto b : data2) std::cout << b << ' ';
    std::cout << std::endl;
    foo();
    data1 += data2;
    for (auto c : data1) std::cout << c << ' ';
    std::cout << std::endl;
}

 

 

 

 

0 Kudos
Shenghong_G_Intel
503 Views

Hi Patrick,

I do spend some time to understand the differences of your 2 versions of code!!! :) And finally, I saw the "Notice the backslash on the second version" description!!

First, I'll explain why adding "\" makes it work. With "\", the attribute line is commented!! And by default, ICC will generate the code for all arch. So, it works for difference arch, but they share the same code in fact.

Second, it is an usage error for your code, you cannot add attribute before "template", instead, below is correct usage:

template <class T>
__attribute__ ((target("default")))
void operator+=(std::vector<T>& v1, std::vector<T>& v2){
    v1.data()[0:v1.size()] += v2.data()[0:v2.size()];
}

Let me know if you still have issues.

Thanks,

Shenghong

0 Kudos
Patrick_P_3
Beginner
503 Views

shenghong-geng (Intel) wrote:

Hi Patrick,

I do spend some time to understand the differences of your 2 versions of code!!! :) And finally, I saw the "Notice the backslash on the second version" description!!

First, I'll explain why adding "\" makes it work. With "\", the attribute line is commented!! And by default, ICC will generate the code for all arch. So, it works for difference arch, but they share the same code in fact.

Second, it is an usage error for your code, you cannot add attribute before "template", instead, below is correct usage:

template <class T>
__attribute__ ((target("default")))
void operator+=(std::vector<T>& v1, std::vector<T>& v2){
    v1.data()[0:v1.size()] += v2.data()[0:v2.size()];
}

Let me know if you still have issues.

Thanks,

Shenghong

1)Thank you very much. I have no further problems related to this, for now anyway.

2) Who's hair-brained idea was it to require the template go before the attribute?! It makes far more sense the other way around! Bah...

0 Kudos
Shenghong_G_Intel
503 Views

Hi Patrick,

Regarding your #2 concern, this is not decided by us, we follow the 'standard' of GCC. Different people may like different style, there is no reason why it dost not accept attribute to put before template, this is totally a design of syntax...:) 

See my testing below:

// Build with: gcc temp.cpp

// works (the way I like)
template <class T>
__attribute__((noinline))
void foo1(T arg);

// works (same with above)
template <class T>
__attribute__((noinline)) void foo2(T arg);

// works (I do not use like this usually, but it works in fact)
template <class T>
void __attribute__((noinline)) foo3(T arg);

// works (the way I also like)
template <class T>
void foo4(T arg) __attribute__((noinline));

// fail, not accepted
// temp.cpp:23:1: error: expected unqualified-id before 'template'
__attribute__((noinline))
template <class T>
void foo5(T arg);

int main(int argc, char** argv) {
  return 0;
}

Thanks,

Shenghong

0 Kudos
Reply